-//===--- Bitcode/Writer/Writer.cpp - Bitcode Writer -----------------------===//
+//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===//
//
// The LLVM Compiler Infrastructure
//
#include "ValueEnumerator.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
+#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
static unsigned getEncodedVisibility(const GlobalValue *GV) {
switch (GV->getVisibility()) {
default: assert(0 && "Invalid visibility!");
- case GlobalValue::DefaultVisibility: return 0;
- case GlobalValue::HiddenVisibility: return 1;
+ case GlobalValue::DefaultVisibility: return 0;
+ case GlobalValue::HiddenVisibility: return 1;
+ case GlobalValue::ProtectedVisibility: return 2;
}
}
}
-/// WriteTypeSymbolTable - Emit a block for the specified type symtab.
-static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- if (TST.empty()) return;
-
- Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3);
-
- // FIXME: Set up the abbrev, we know how many types there are!
- // FIXME: We know if the type names can use 7-bit ascii.
-
- SmallVector<unsigned, 64> NameVals;
-
- for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
- TI != TE; ++TI) {
- unsigned AbbrevToUse = 0;
-
- // TST_ENTRY: [typeid, namelen, namechar x N]
- NameVals.push_back(VE.getTypeID(TI->second));
-
- const std::string &Str = TI->first;
- NameVals.push_back(Str.size());
- for (unsigned i = 0, e = Str.size(); i != e; ++i)
- NameVals.push_back(Str[i]);
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, AbbrevToUse);
- NameVals.clear();
- }
-
- Stream.ExitBlock();
-}
-
-// Emit names for globals/functions etc.
-static void WriteValueSymbolTable(const ValueSymbolTable &VST,
- const ValueEnumerator &VE,
- BitstreamWriter &Stream) {
- if (VST.empty()) return;
- Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 3);
-
- // FIXME: Set up the abbrev, we know how many values there are!
- // FIXME: We know if the type names can use 7-bit ascii.
- SmallVector<unsigned, 64> NameVals;
-
- for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end();
- SI != SE; ++SI) {
- unsigned AbbrevToUse = 0;
-
- // VST_ENTRY: [valueid, namelen, namechar x N]
- NameVals.push_back(VE.getValueID(SI->getValue()));
-
- NameVals.push_back(SI->getKeyLength());
- for (const char *P = SI->getKeyData(),
- *E = SI->getKeyData()+SI->getKeyLength(); P != E; ++P)
- NameVals.push_back((unsigned char)*P);
-
- // Emit the finished record.
- Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, AbbrevToUse);
- NameVals.clear();
- }
- Stream.ExitBlock();
-}
-
static void WriteConstants(unsigned FirstVal, unsigned LastVal,
const ValueEnumerator &VE,
BitstreamWriter &Stream) {
Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 2);
- // FIXME: Install and use abbrevs to reduce size.
+ // FIXME: Install and use abbrevs to reduce size. Install them globally so
+ // they don't need to be reemitted for each function body.
SmallVector<uint64_t, 64> Record;
}
}
+/// WriteInstruction - Emit an instruction to the specified stream.
+static void WriteInstruction(const Instruction &I, ValueEnumerator &VE,
+ BitstreamWriter &Stream,
+ SmallVector<unsigned, 64> &Vals) {
+ unsigned Code = 0;
+ unsigned AbbrevToUse = 0;
+ switch (I.getOpcode()) {
+ default:
+ if (Instruction::isCast(I.getOpcode())) {
+ Code = bitc::FUNC_CODE_INST_CAST;
+ Vals.push_back(GetEncodedCastOpcode(I.getOpcode()));
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ } else {
+ assert(isa<BinaryOperator>(I) && "Unknown instruction!");
+ Code = bitc::FUNC_CODE_INST_BINOP;
+ Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode()));
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ }
+ break;
+
+ case Instruction::GetElementPtr:
+ Code = bitc::FUNC_CODE_INST_GEP;
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i) {
+ Vals.push_back(VE.getTypeID(I.getOperand(i)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ }
+ break;
+ case Instruction::Select:
+ Code = bitc::FUNC_CODE_INST_SELECT;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ Vals.push_back(VE.getValueID(I.getOperand(2)));
+ break;
+ case Instruction::ExtractElement:
+ Code = bitc::FUNC_CODE_INST_EXTRACTELT;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ break;
+ case Instruction::InsertElement:
+ Code = bitc::FUNC_CODE_INST_INSERTELT;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ Vals.push_back(VE.getValueID(I.getOperand(2)));
+ break;
+ case Instruction::ShuffleVector:
+ Code = bitc::FUNC_CODE_INST_SHUFFLEVEC;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ Vals.push_back(VE.getValueID(I.getOperand(2)));
+ break;
+ case Instruction::ICmp:
+ case Instruction::FCmp:
+ Code = bitc::FUNC_CODE_INST_CMP;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ Vals.push_back(cast<CmpInst>(I).getPredicate());
+ break;
+
+ case Instruction::Ret:
+ Code = bitc::FUNC_CODE_INST_RET;
+ if (I.getNumOperands()) {
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ }
+ break;
+ case Instruction::Br:
+ Code = bitc::FUNC_CODE_INST_BR;
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ if (cast<BranchInst>(I).isConditional()) {
+ Vals.push_back(VE.getValueID(I.getOperand(1)));
+ Vals.push_back(VE.getValueID(I.getOperand(2)));
+ }
+ break;
+ case Instruction::Switch:
+ Code = bitc::FUNC_CODE_INST_SWITCH;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ break;
+ case Instruction::Invoke: {
+ Code = bitc::FUNC_CODE_INST_INVOKE;
+ Vals.push_back(cast<InvokeInst>(I).getCallingConv());
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // callee
+ Vals.push_back(VE.getValueID(I.getOperand(1))); // normal
+ Vals.push_back(VE.getValueID(I.getOperand(2))); // unwind
+
+ // Emit value #'s for the fixed parameters.
+ const PointerType *PTy = cast<PointerType>(I.getOperand(0)->getType());
+ const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+ Vals.push_back(VE.getValueID(I.getOperand(i+3))); // fixed param.
+
+ // Emit type/value pairs for varargs params.
+ if (FTy->isVarArg()) {
+ unsigned NumVarargs = I.getNumOperands()-3-FTy->getNumParams();
+ Vals.push_back(NumVarargs);
+ for (unsigned i = I.getNumOperands()-NumVarargs, e = I.getNumOperands();
+ i != e; ++i) {
+ Vals.push_back(VE.getTypeID(I.getOperand(i)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ }
+ }
+ break;
+ }
+ case Instruction::Unwind:
+ Code = bitc::FUNC_CODE_INST_UNWIND;
+ break;
+ case Instruction::Unreachable:
+ Code = bitc::FUNC_CODE_INST_UNREACHABLE;
+ break;
+
+ case Instruction::PHI:
+ Code = bitc::FUNC_CODE_INST_PHI;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(I.getNumOperands());
+ for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ break;
+
+ case Instruction::Malloc:
+ Code = bitc::FUNC_CODE_INST_MALLOC;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // size.
+ Vals.push_back(Log2_32(cast<MallocInst>(I).getAlignment())+1);
+ break;
+
+ case Instruction::Free:
+ Code = bitc::FUNC_CODE_INST_FREE;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0)));
+ break;
+
+ case Instruction::Alloca:
+ Code = bitc::FUNC_CODE_INST_ALLOCA;
+ Vals.push_back(VE.getTypeID(I.getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // size.
+ Vals.push_back(Log2_32(cast<AllocaInst>(I).getAlignment())+1);
+ break;
+
+ case Instruction::Load:
+ Code = bitc::FUNC_CODE_INST_LOAD;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // ptr.
+ Vals.push_back(Log2_32(cast<LoadInst>(I).getAlignment())+1);
+ Vals.push_back(cast<LoadInst>(I).isVolatile());
+ break;
+ case Instruction::Store:
+ Code = bitc::FUNC_CODE_INST_STORE;
+ Vals.push_back(VE.getTypeID(I.getOperand(1)->getType())); // Pointer
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // val.
+ Vals.push_back(VE.getValueID(I.getOperand(1))); // ptr.
+ Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
+ Vals.push_back(cast<StoreInst>(I).isVolatile());
+ break;
+ case Instruction::Call: {
+ Code = bitc::FUNC_CODE_INST_CALL;
+ Vals.push_back((cast<CallInst>(I).getCallingConv() << 1) |
+ cast<CallInst>(I).isTailCall());
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // callee
+
+ // Emit value #'s for the fixed parameters.
+ const PointerType *PTy = cast<PointerType>(I.getOperand(0)->getType());
+ const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
+ for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
+ Vals.push_back(VE.getValueID(I.getOperand(i+1))); // fixed param.
+
+ // Emit type/value pairs for varargs params.
+ if (FTy->isVarArg()) {
+ unsigned NumVarargs = I.getNumOperands()-1-FTy->getNumParams();
+ for (unsigned i = I.getNumOperands()-NumVarargs, e = I.getNumOperands();
+ i != e; ++i) {
+ Vals.push_back(VE.getTypeID(I.getOperand(i)->getType()));
+ Vals.push_back(VE.getValueID(I.getOperand(i)));
+ }
+ }
+ break;
+ }
+ case Instruction::VAArg:
+ Code = bitc::FUNC_CODE_INST_VAARG;
+ Vals.push_back(VE.getTypeID(I.getOperand(0)->getType())); // valistty
+ Vals.push_back(VE.getValueID(I.getOperand(0))); // valist.
+ Vals.push_back(VE.getTypeID(I.getType())); // restype.
+ break;
+ }
+
+ Stream.EmitRecord(Code, Vals, AbbrevToUse);
+ Vals.clear();
+}
+
+// Emit names for globals/functions etc.
+static void WriteValueSymbolTable(const ValueSymbolTable &VST,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ if (VST.empty()) return;
+ Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 3);
+
+ // FIXME: Set up the abbrev, we know how many values there are!
+ // FIXME: We know if the type names can use 7-bit ascii.
+ SmallVector<unsigned, 64> NameVals;
+
+ for (ValueSymbolTable::const_iterator SI = VST.begin(), SE = VST.end();
+ SI != SE; ++SI) {
+ unsigned AbbrevToUse = 0;
+
+ // VST_ENTRY: [valueid, namelen, namechar x N]
+ // VST_BBENTRY: [bbid, namelen, namechar x N]
+ unsigned Code;
+ if (isa<BasicBlock>(SI->getValue())) {
+ Code = bitc::VST_CODE_BBENTRY;
+ } else {
+ Code = bitc::VST_CODE_ENTRY;
+ }
+
+ NameVals.push_back(VE.getValueID(SI->getValue()));
+ NameVals.push_back(SI->getKeyLength());
+ for (const char *P = SI->getKeyData(),
+ *E = SI->getKeyData()+SI->getKeyLength(); P != E; ++P)
+ NameVals.push_back((unsigned char)*P);
+
+ // Emit the finished record.
+ Stream.EmitRecord(Code, NameVals, AbbrevToUse);
+ NameVals.clear();
+ }
+ Stream.ExitBlock();
+}
+
+/// WriteFunction - Emit a function body to the module stream.
+static void WriteFunction(const Function &F, ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 3);
+ VE.incorporateFunction(F);
+
+ SmallVector<unsigned, 64> Vals;
+
+ // Emit the number of basic blocks, so the reader can create them ahead of
+ // time.
+ Vals.push_back(VE.getBasicBlocks().size());
+ Stream.EmitRecord(bitc::FUNC_CODE_DECLAREBLOCKS, Vals);
+ Vals.clear();
+
+ // FIXME: Function attributes?
+
+ // If there are function-local constants, emit them now.
+ unsigned CstStart, CstEnd;
+ VE.getFunctionConstantRange(CstStart, CstEnd);
+ WriteConstants(CstStart, CstEnd, VE, Stream);
+
+ // Finally, emit all the instructions, in order.
+ for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I)
+ WriteInstruction(*I, VE, Stream, Vals);
+
+ // Emit names for all the instructions etc.
+ WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream);
+
+ VE.purgeFunction();
+ Stream.ExitBlock();
+}
+
+/// WriteTypeSymbolTable - Emit a block for the specified type symtab.
+static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
+ const ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ if (TST.empty()) return;
+
+ Stream.EnterSubblock(bitc::TYPE_SYMTAB_BLOCK_ID, 3);
+
+ // FIXME: Set up the abbrev, we know how many types there are!
+ // FIXME: We know if the type names can use 7-bit ascii.
+
+ SmallVector<unsigned, 64> NameVals;
+
+ for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
+ TI != TE; ++TI) {
+ unsigned AbbrevToUse = 0;
+
+ // TST_ENTRY: [typeid, namelen, namechar x N]
+ NameVals.push_back(VE.getTypeID(TI->second));
+
+ const std::string &Str = TI->first;
+ NameVals.push_back(Str.size());
+ for (unsigned i = 0, e = Str.size(); i != e; ++i)
+ NameVals.push_back(Str[i]);
+
+ // Emit the finished record.
+ Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, AbbrevToUse);
+ NameVals.clear();
+ }
+
+ Stream.ExitBlock();
+}
+
+
/// WriteModule - Emit the specified module to the bitstream.
static void WriteModule(const Module *M, BitstreamWriter &Stream) {
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
// Emit the version number if it is non-zero.
if (CurVersion) {
- SmallVector<unsigned, 1> VersionVals;
- VersionVals.push_back(CurVersion);
- Stream.EmitRecord(bitc::MODULE_CODE_VERSION, VersionVals);
+ SmallVector<unsigned, 1> Vals;
+ Vals.push_back(CurVersion);
+ Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
}
// Analyze the module, enumerating globals, functions, etc.
// Emit constants.
WriteModuleConstants(VE, Stream);
+ // If we have any aggregate values in the value table, purge them - these can
+ // only be used to initialize global variables. Doing so makes the value
+ // namespace smaller for code in functions.
+ int NumNonAggregates = VE.PurgeAggregateValues();
+ if (NumNonAggregates != -1) {
+ SmallVector<unsigned, 1> Vals;
+ Vals.push_back(NumNonAggregates);
+ Stream.EmitRecord(bitc::MODULE_CODE_PURGEVALS, Vals);
+ }
+
+ // Emit function bodies.
+ for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
+ if (!I->isDeclaration())
+ WriteFunction(*I, VE, Stream);
+
// Emit the type symbol table information.
WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);