2007-04-29 13:31:57 +08:00
|
|
|
//===--- Bitcode/Writer/BitcodeWriter.cpp - Bitcode Writer ----------------===//
|
2007-04-22 14:24:45 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
2007-12-30 04:36:04 +08:00
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
2007-04-22 14:24:45 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Bitcode writer implementation.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "llvm/Bitcode/ReaderWriter.h"
|
|
|
|
#include "llvm/Bitcode/BitstreamWriter.h"
|
2007-04-23 09:01:37 +08:00
|
|
|
#include "llvm/Bitcode/LLVMBitCodes.h"
|
2007-04-22 14:24:45 +08:00
|
|
|
#include "ValueEnumerator.h"
|
2007-04-24 08:16:04 +08:00
|
|
|
#include "llvm/Constants.h"
|
2007-04-22 14:24:45 +08:00
|
|
|
#include "llvm/DerivedTypes.h"
|
2007-05-06 09:58:20 +08:00
|
|
|
#include "llvm/InlineAsm.h"
|
2007-04-26 13:53:54 +08:00
|
|
|
#include "llvm/Instructions.h"
|
2009-05-11 04:57:05 +08:00
|
|
|
#include "llvm/MDNode.h"
|
2007-04-22 14:24:45 +08:00
|
|
|
#include "llvm/Module.h"
|
|
|
|
#include "llvm/TypeSymbolTable.h"
|
2007-04-24 04:35:01 +08:00
|
|
|
#include "llvm/ValueSymbolTable.h"
|
2007-04-22 14:24:45 +08:00
|
|
|
#include "llvm/Support/MathExtras.h"
|
2008-08-24 05:33:24 +08:00
|
|
|
#include "llvm/Support/Streams.h"
|
2008-10-23 01:39:14 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-06-06 15:24:01 +08:00
|
|
|
#include "llvm/System/Program.h"
|
2007-04-22 14:24:45 +08:00
|
|
|
using namespace llvm;
|
|
|
|
|
2007-05-05 04:52:02 +08:00
|
|
|
/// These are manifest constants used by the bitcode writer. They do not need to
|
|
|
|
/// be kept in sync with the reader, but need to be consistent within this file.
|
|
|
|
enum {
|
|
|
|
CurVersion = 0,
|
|
|
|
|
|
|
|
// VALUE_SYMTAB_BLOCK abbrev id's.
|
|
|
|
VST_ENTRY_8_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
|
2007-05-05 04:58:35 +08:00
|
|
|
VST_ENTRY_7_ABBREV,
|
2007-05-05 09:26:50 +08:00
|
|
|
VST_ENTRY_6_ABBREV,
|
2007-05-05 15:36:14 +08:00
|
|
|
VST_BBENTRY_6_ABBREV,
|
|
|
|
|
|
|
|
// CONSTANTS_BLOCK abbrev id's.
|
|
|
|
CONSTANTS_SETTYPE_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
|
|
|
|
CONSTANTS_INTEGER_ABBREV,
|
|
|
|
CONSTANTS_CE_CAST_Abbrev,
|
2007-05-05 15:44:49 +08:00
|
|
|
CONSTANTS_NULL_Abbrev,
|
|
|
|
|
|
|
|
// FUNCTION_BLOCK abbrev id's.
|
2007-05-06 09:28:01 +08:00
|
|
|
FUNCTION_INST_LOAD_ABBREV = bitc::FIRST_APPLICATION_ABBREV,
|
2007-05-06 10:38:57 +08:00
|
|
|
FUNCTION_INST_BINOP_ABBREV,
|
|
|
|
FUNCTION_INST_CAST_ABBREV,
|
2007-05-06 09:28:01 +08:00
|
|
|
FUNCTION_INST_RET_VOID_ABBREV,
|
|
|
|
FUNCTION_INST_RET_VAL_ABBREV,
|
|
|
|
FUNCTION_INST_UNREACHABLE_ABBREV
|
2007-05-05 04:52:02 +08:00
|
|
|
};
|
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
|
2007-04-24 15:07:11 +08:00
|
|
|
static unsigned GetEncodedCastOpcode(unsigned Opcode) {
|
|
|
|
switch (Opcode) {
|
|
|
|
default: assert(0 && "Unknown cast instruction!");
|
|
|
|
case Instruction::Trunc : return bitc::CAST_TRUNC;
|
|
|
|
case Instruction::ZExt : return bitc::CAST_ZEXT;
|
|
|
|
case Instruction::SExt : return bitc::CAST_SEXT;
|
|
|
|
case Instruction::FPToUI : return bitc::CAST_FPTOUI;
|
|
|
|
case Instruction::FPToSI : return bitc::CAST_FPTOSI;
|
|
|
|
case Instruction::UIToFP : return bitc::CAST_UITOFP;
|
|
|
|
case Instruction::SIToFP : return bitc::CAST_SITOFP;
|
|
|
|
case Instruction::FPTrunc : return bitc::CAST_FPTRUNC;
|
|
|
|
case Instruction::FPExt : return bitc::CAST_FPEXT;
|
|
|
|
case Instruction::PtrToInt: return bitc::CAST_PTRTOINT;
|
|
|
|
case Instruction::IntToPtr: return bitc::CAST_INTTOPTR;
|
|
|
|
case Instruction::BitCast : return bitc::CAST_BITCAST;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned GetEncodedBinaryOpcode(unsigned Opcode) {
|
|
|
|
switch (Opcode) {
|
|
|
|
default: assert(0 && "Unknown binary instruction!");
|
2009-06-05 06:49:04 +08:00
|
|
|
case Instruction::Add:
|
|
|
|
case Instruction::FAdd: return bitc::BINOP_ADD;
|
|
|
|
case Instruction::Sub:
|
|
|
|
case Instruction::FSub: return bitc::BINOP_SUB;
|
|
|
|
case Instruction::Mul:
|
|
|
|
case Instruction::FMul: return bitc::BINOP_MUL;
|
2007-04-24 15:07:11 +08:00
|
|
|
case Instruction::UDiv: return bitc::BINOP_UDIV;
|
|
|
|
case Instruction::FDiv:
|
|
|
|
case Instruction::SDiv: return bitc::BINOP_SDIV;
|
|
|
|
case Instruction::URem: return bitc::BINOP_UREM;
|
|
|
|
case Instruction::FRem:
|
|
|
|
case Instruction::SRem: return bitc::BINOP_SREM;
|
|
|
|
case Instruction::Shl: return bitc::BINOP_SHL;
|
|
|
|
case Instruction::LShr: return bitc::BINOP_LSHR;
|
|
|
|
case Instruction::AShr: return bitc::BINOP_ASHR;
|
|
|
|
case Instruction::And: return bitc::BINOP_AND;
|
|
|
|
case Instruction::Or: return bitc::BINOP_OR;
|
|
|
|
case Instruction::Xor: return bitc::BINOP_XOR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
static void WriteStringRecord(unsigned Code, const std::string &Str,
|
|
|
|
unsigned AbbrevToUse, BitstreamWriter &Stream) {
|
|
|
|
SmallVector<unsigned, 64> Vals;
|
|
|
|
|
2007-05-05 03:11:41 +08:00
|
|
|
// Code: [strchar x N]
|
2007-04-22 14:24:45 +08:00
|
|
|
for (unsigned i = 0, e = Str.size(); i != e; ++i)
|
|
|
|
Vals.push_back(Str[i]);
|
|
|
|
|
|
|
|
// Emit the finished record.
|
|
|
|
Stream.EmitRecord(Code, Vals, AbbrevToUse);
|
|
|
|
}
|
|
|
|
|
2007-05-04 08:44:52 +08:00
|
|
|
// Emit information about parameter attributes.
|
2008-09-26 05:00:45 +08:00
|
|
|
static void WriteAttributeTable(const ValueEnumerator &VE,
|
2007-05-04 08:44:52 +08:00
|
|
|
BitstreamWriter &Stream) {
|
2008-09-26 05:00:45 +08:00
|
|
|
const std::vector<AttrListPtr> &Attrs = VE.getAttributes();
|
2007-05-04 08:44:52 +08:00
|
|
|
if (Attrs.empty()) return;
|
|
|
|
|
2007-05-04 10:59:04 +08:00
|
|
|
Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3);
|
|
|
|
|
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
|
2008-09-26 05:00:45 +08:00
|
|
|
const AttrListPtr &A = Attrs[i];
|
2008-03-13 01:45:29 +08:00
|
|
|
for (unsigned i = 0, e = A.getNumSlots(); i != e; ++i) {
|
2008-09-26 05:00:45 +08:00
|
|
|
const AttributeWithIndex &PAWI = A.getSlot(i);
|
2008-03-13 01:45:29 +08:00
|
|
|
Record.push_back(PAWI.Index);
|
2008-12-19 17:38:31 +08:00
|
|
|
|
|
|
|
// FIXME: remove in LLVM 3.0
|
|
|
|
// Store the alignment in the bitcode as a 16-bit raw value instead of a
|
|
|
|
// 5-bit log2 encoded value. Shift the bits above the alignment up by
|
|
|
|
// 11 bits.
|
|
|
|
uint64_t FauxAttr = PAWI.Attrs & 0xffff;
|
|
|
|
if (PAWI.Attrs & Attribute::Alignment)
|
|
|
|
FauxAttr |= (1ull<<16)<<(((PAWI.Attrs & Attribute::Alignment)-1) >> 16);
|
|
|
|
FauxAttr |= (PAWI.Attrs & (0x3FFull << 21)) << 11;
|
|
|
|
|
|
|
|
Record.push_back(FauxAttr);
|
2007-05-04 10:59:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
|
|
|
|
Record.clear();
|
|
|
|
}
|
2007-05-04 08:44:52 +08:00
|
|
|
|
2007-05-04 10:59:04 +08:00
|
|
|
Stream.ExitBlock();
|
2007-05-04 08:44:52 +08:00
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
/// WriteTypeTable - Write out the type table for a module.
|
|
|
|
static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
|
|
|
|
const ValueEnumerator::TypeList &TypeList = VE.getTypes();
|
|
|
|
|
|
|
|
Stream.EnterSubblock(bitc::TYPE_BLOCK_ID, 4 /*count from # abbrevs */);
|
|
|
|
SmallVector<uint64_t, 64> TypeVals;
|
|
|
|
|
2007-05-05 14:30:12 +08:00
|
|
|
// Abbrev for TYPE_CODE_POINTER.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_POINTER));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
2007-12-12 16:44:39 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(0)); // Addrspace = 0
|
2007-05-05 14:30:12 +08:00
|
|
|
unsigned PtrAbbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
|
|
|
|
// Abbrev for TYPE_CODE_FUNCTION.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_FUNCTION));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isvararg
|
2007-11-28 01:48:06 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(0)); // FIXME: DEAD value, remove in LLVM 3.0
|
2007-05-05 14:30:12 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
unsigned FunctionAbbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
|
|
|
|
// Abbrev for TYPE_CODE_STRUCT.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_STRUCT));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ispacked
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
unsigned StructAbbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
|
|
|
|
// Abbrev for TYPE_CODE_ARRAY.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::TYPE_CODE_ARRAY));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // size
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
unsigned ArrayAbbrev = Stream.EmitAbbrev(Abbv);
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
// Emit an entry count so the reader can reserve space.
|
|
|
|
TypeVals.push_back(TypeList.size());
|
|
|
|
Stream.EmitRecord(bitc::TYPE_CODE_NUMENTRY, TypeVals);
|
|
|
|
TypeVals.clear();
|
|
|
|
|
|
|
|
// Loop over all of the types, emitting each in turn.
|
|
|
|
for (unsigned i = 0, e = TypeList.size(); i != e; ++i) {
|
|
|
|
const Type *T = TypeList[i].first;
|
|
|
|
int AbbrevToUse = 0;
|
|
|
|
unsigned Code = 0;
|
|
|
|
|
|
|
|
switch (T->getTypeID()) {
|
|
|
|
default: assert(0 && "Unknown type!");
|
|
|
|
case Type::VoidTyID: Code = bitc::TYPE_CODE_VOID; break;
|
|
|
|
case Type::FloatTyID: Code = bitc::TYPE_CODE_FLOAT; break;
|
|
|
|
case Type::DoubleTyID: Code = bitc::TYPE_CODE_DOUBLE; break;
|
2007-08-03 09:03:46 +08:00
|
|
|
case Type::X86_FP80TyID: Code = bitc::TYPE_CODE_X86_FP80; break;
|
|
|
|
case Type::FP128TyID: Code = bitc::TYPE_CODE_FP128; break;
|
|
|
|
case Type::PPC_FP128TyID: Code = bitc::TYPE_CODE_PPC_FP128; break;
|
2007-04-22 14:24:45 +08:00
|
|
|
case Type::LabelTyID: Code = bitc::TYPE_CODE_LABEL; break;
|
|
|
|
case Type::OpaqueTyID: Code = bitc::TYPE_CODE_OPAQUE; break;
|
2009-05-30 13:06:04 +08:00
|
|
|
case Type::MetadataTyID: Code = bitc::TYPE_CODE_METADATA; break;
|
2007-04-22 14:24:45 +08:00
|
|
|
case Type::IntegerTyID:
|
|
|
|
// INTEGER: [width]
|
|
|
|
Code = bitc::TYPE_CODE_INTEGER;
|
|
|
|
TypeVals.push_back(cast<IntegerType>(T)->getBitWidth());
|
|
|
|
break;
|
2007-12-11 20:20:47 +08:00
|
|
|
case Type::PointerTyID: {
|
2007-12-11 16:59:05 +08:00
|
|
|
const PointerType *PTy = cast<PointerType>(T);
|
2007-12-12 16:44:39 +08:00
|
|
|
// POINTER: [pointee type, address space]
|
2007-04-22 14:24:45 +08:00
|
|
|
Code = bitc::TYPE_CODE_POINTER;
|
2007-12-11 16:59:05 +08:00
|
|
|
TypeVals.push_back(VE.getTypeID(PTy->getElementType()));
|
2007-12-12 16:44:39 +08:00
|
|
|
unsigned AddressSpace = PTy->getAddressSpace();
|
|
|
|
TypeVals.push_back(AddressSpace);
|
|
|
|
if (AddressSpace == 0) AbbrevToUse = PtrAbbrev;
|
2007-04-22 14:24:45 +08:00
|
|
|
break;
|
2007-12-11 20:20:47 +08:00
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
case Type::FunctionTyID: {
|
|
|
|
const FunctionType *FT = cast<FunctionType>(T);
|
2007-11-28 01:48:06 +08:00
|
|
|
// FUNCTION: [isvararg, attrid, retty, paramty x N]
|
2007-04-22 14:24:45 +08:00
|
|
|
Code = bitc::TYPE_CODE_FUNCTION;
|
|
|
|
TypeVals.push_back(FT->isVarArg());
|
2007-11-28 01:48:06 +08:00
|
|
|
TypeVals.push_back(0); // FIXME: DEAD: remove in llvm 3.0
|
2007-04-22 14:24:45 +08:00
|
|
|
TypeVals.push_back(VE.getTypeID(FT->getReturnType()));
|
|
|
|
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
|
|
|
|
TypeVals.push_back(VE.getTypeID(FT->getParamType(i)));
|
2007-05-05 14:30:12 +08:00
|
|
|
AbbrevToUse = FunctionAbbrev;
|
2007-04-22 14:24:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::StructTyID: {
|
|
|
|
const StructType *ST = cast<StructType>(T);
|
2007-05-05 14:30:12 +08:00
|
|
|
// STRUCT: [ispacked, eltty x N]
|
2007-04-22 14:24:45 +08:00
|
|
|
Code = bitc::TYPE_CODE_STRUCT;
|
|
|
|
TypeVals.push_back(ST->isPacked());
|
2007-05-05 03:11:41 +08:00
|
|
|
// Output all of the element types.
|
2007-04-22 14:24:45 +08:00
|
|
|
for (StructType::element_iterator I = ST->element_begin(),
|
|
|
|
E = ST->element_end(); I != E; ++I)
|
|
|
|
TypeVals.push_back(VE.getTypeID(*I));
|
2007-05-05 14:30:12 +08:00
|
|
|
AbbrevToUse = StructAbbrev;
|
2007-04-22 14:24:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::ArrayTyID: {
|
|
|
|
const ArrayType *AT = cast<ArrayType>(T);
|
|
|
|
// ARRAY: [numelts, eltty]
|
|
|
|
Code = bitc::TYPE_CODE_ARRAY;
|
|
|
|
TypeVals.push_back(AT->getNumElements());
|
|
|
|
TypeVals.push_back(VE.getTypeID(AT->getElementType()));
|
2007-05-05 14:30:12 +08:00
|
|
|
AbbrevToUse = ArrayAbbrev;
|
2007-04-22 14:24:45 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case Type::VectorTyID: {
|
|
|
|
const VectorType *VT = cast<VectorType>(T);
|
|
|
|
// VECTOR [numelts, eltty]
|
|
|
|
Code = bitc::TYPE_CODE_VECTOR;
|
|
|
|
TypeVals.push_back(VT->getNumElements());
|
|
|
|
TypeVals.push_back(VE.getTypeID(VT->getElementType()));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit the finished record.
|
|
|
|
Stream.EmitRecord(Code, TypeVals, AbbrevToUse);
|
|
|
|
TypeVals.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned getEncodedLinkage(const GlobalValue *GV) {
|
|
|
|
switch (GV->getLinkage()) {
|
|
|
|
default: assert(0 && "Invalid linkage!");
|
2007-05-12 07:51:59 +08:00
|
|
|
case GlobalValue::GhostLinkage: // Map ghost linkage onto external.
|
2007-04-22 14:24:45 +08:00
|
|
|
case GlobalValue::ExternalLinkage: return 0;
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
case GlobalValue::WeakAnyLinkage: return 1;
|
2007-04-22 14:24:45 +08:00
|
|
|
case GlobalValue::AppendingLinkage: return 2;
|
|
|
|
case GlobalValue::InternalLinkage: return 3;
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
case GlobalValue::LinkOnceAnyLinkage: return 4;
|
2007-04-22 14:24:45 +08:00
|
|
|
case GlobalValue::DLLImportLinkage: return 5;
|
|
|
|
case GlobalValue::DLLExportLinkage: return 6;
|
2009-03-11 16:08:06 +08:00
|
|
|
case GlobalValue::ExternalWeakLinkage: return 7;
|
2009-03-12 04:14:15 +08:00
|
|
|
case GlobalValue::CommonLinkage: return 8;
|
2009-01-16 04:18:42 +08:00
|
|
|
case GlobalValue::PrivateLinkage: return 9;
|
Introduce new linkage types linkonce_odr, weak_odr, common_odr
and extern_weak_odr. These are the same as the non-odr versions,
except that they indicate that the global will only be overridden
by an *equivalent* global. In C, a function with weak linkage can
be overridden by a function which behaves completely differently.
This means that IP passes have to skip weak functions, since any
deductions made from the function definition might be wrong, since
the definition could be replaced by something completely different
at link time. This is not allowed in C++, thanks to the ODR
(One-Definition-Rule): if a function is replaced by another at
link-time, then the new function must be the same as the original
function. If a language knows that a function or other global can
only be overridden by an equivalent global, it can give it the
weak_odr linkage type, and the optimizers will understand that it
is alright to make deductions based on the function body. The
code generators on the other hand map weak and weak_odr linkage
to the same thing.
llvm-svn: 66339
2009-03-07 23:45:40 +08:00
|
|
|
case GlobalValue::WeakODRLinkage: return 10;
|
|
|
|
case GlobalValue::LinkOnceODRLinkage: return 11;
|
2009-04-13 13:44:34 +08:00
|
|
|
case GlobalValue::AvailableExternallyLinkage: return 12;
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned getEncodedVisibility(const GlobalValue *GV) {
|
|
|
|
switch (GV->getVisibility()) {
|
|
|
|
default: assert(0 && "Invalid visibility!");
|
2007-04-30 04:56:48 +08:00
|
|
|
case GlobalValue::DefaultVisibility: return 0;
|
|
|
|
case GlobalValue::HiddenVisibility: return 1;
|
|
|
|
case GlobalValue::ProtectedVisibility: return 2;
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit top-level description of module, including target triple, inline asm,
|
|
|
|
// descriptors for global variables, and function prototype info.
|
|
|
|
static void WriteModuleInfo(const Module *M, const ValueEnumerator &VE,
|
|
|
|
BitstreamWriter &Stream) {
|
|
|
|
// Emit the list of dependent libraries for the Module.
|
|
|
|
for (Module::lib_iterator I = M->lib_begin(), E = M->lib_end(); I != E; ++I)
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_DEPLIB, *I, 0/*TODO*/, Stream);
|
|
|
|
|
|
|
|
// Emit various pieces of data attached to a module.
|
|
|
|
if (!M->getTargetTriple().empty())
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_TRIPLE, M->getTargetTriple(),
|
|
|
|
0/*TODO*/, Stream);
|
|
|
|
if (!M->getDataLayout().empty())
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_DATALAYOUT, M->getDataLayout(),
|
|
|
|
0/*TODO*/, Stream);
|
|
|
|
if (!M->getModuleInlineAsm().empty())
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_ASM, M->getModuleInlineAsm(),
|
|
|
|
0/*TODO*/, Stream);
|
|
|
|
|
2008-08-18 02:44:35 +08:00
|
|
|
// Emit information about sections and GC, computing how many there are. Also
|
|
|
|
// compute the maximum alignment value.
|
2007-04-22 14:24:45 +08:00
|
|
|
std::map<std::string, unsigned> SectionMap;
|
2008-08-18 02:44:35 +08:00
|
|
|
std::map<std::string, unsigned> GCMap;
|
2007-04-24 00:04:05 +08:00
|
|
|
unsigned MaxAlignment = 0;
|
2007-04-24 02:58:34 +08:00
|
|
|
unsigned MaxGlobalType = 0;
|
2007-04-22 14:24:45 +08:00
|
|
|
for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end();
|
|
|
|
GV != E; ++GV) {
|
2007-04-24 00:04:05 +08:00
|
|
|
MaxAlignment = std::max(MaxAlignment, GV->getAlignment());
|
2007-04-24 02:58:34 +08:00
|
|
|
MaxGlobalType = std::max(MaxGlobalType, VE.getTypeID(GV->getType()));
|
2007-04-24 00:04:05 +08:00
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
if (!GV->hasSection()) continue;
|
|
|
|
// Give section names unique ID's.
|
|
|
|
unsigned &Entry = SectionMap[GV->getSection()];
|
|
|
|
if (Entry != 0) continue;
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, GV->getSection(),
|
|
|
|
0/*TODO*/, Stream);
|
|
|
|
Entry = SectionMap.size();
|
|
|
|
}
|
|
|
|
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
2007-04-24 00:04:05 +08:00
|
|
|
MaxAlignment = std::max(MaxAlignment, F->getAlignment());
|
2007-12-10 11:18:06 +08:00
|
|
|
if (F->hasSection()) {
|
|
|
|
// Give section names unique ID's.
|
|
|
|
unsigned &Entry = SectionMap[F->getSection()];
|
|
|
|
if (!Entry) {
|
|
|
|
WriteStringRecord(bitc::MODULE_CODE_SECTIONNAME, F->getSection(),
|
|
|
|
0/*TODO*/, Stream);
|
|
|
|
Entry = SectionMap.size();
|
|
|
|
}
|
|
|
|
}
|
2008-08-18 02:44:35 +08:00
|
|
|
if (F->hasGC()) {
|
|
|
|
// Same for GC names.
|
|
|
|
unsigned &Entry = GCMap[F->getGC()];
|
2007-12-10 11:18:06 +08:00
|
|
|
if (!Entry) {
|
2008-08-18 02:44:35 +08:00
|
|
|
WriteStringRecord(bitc::MODULE_CODE_GCNAME, F->getGC(),
|
2007-12-10 11:18:06 +08:00
|
|
|
0/*TODO*/, Stream);
|
2008-08-18 02:44:35 +08:00
|
|
|
Entry = GCMap.size();
|
2007-12-10 11:18:06 +08:00
|
|
|
}
|
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|
|
|
|
|
2007-04-24 00:04:05 +08:00
|
|
|
// Emit abbrev for globals, now that we know # sections and max alignment.
|
|
|
|
unsigned SimpleGVarAbbrev = 0;
|
2007-04-24 02:58:34 +08:00
|
|
|
if (!M->global_empty()) {
|
2007-04-24 00:04:05 +08:00
|
|
|
// Add an abbrev for common globals with no visibility or thread localness.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::MODULE_CODE_GLOBALVAR));
|
2007-05-05 04:34:50 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
2007-04-24 02:58:34 +08:00
|
|
|
Log2_32_Ceil(MaxGlobalType+1)));
|
2007-05-05 04:34:50 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constant.
|
2007-04-24 00:04:05 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Initializer.
|
2008-05-16 04:49:28 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // Linkage.
|
2007-05-05 04:34:50 +08:00
|
|
|
if (MaxAlignment == 0) // Alignment.
|
2007-04-24 00:04:05 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(0));
|
|
|
|
else {
|
|
|
|
unsigned MaxEncAlignment = Log2_32(MaxAlignment)+1;
|
2007-05-05 04:34:50 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
2007-04-24 02:58:34 +08:00
|
|
|
Log2_32_Ceil(MaxEncAlignment+1)));
|
2007-04-24 00:04:05 +08:00
|
|
|
}
|
|
|
|
if (SectionMap.empty()) // Section.
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(0));
|
|
|
|
else
|
2007-05-05 04:34:50 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
2007-04-24 11:29:47 +08:00
|
|
|
Log2_32_Ceil(SectionMap.size()+1)));
|
2007-04-24 00:04:05 +08:00
|
|
|
// Don't bother emitting vis + thread local.
|
|
|
|
SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
// Emit the global variable information.
|
|
|
|
SmallVector<unsigned, 64> Vals;
|
|
|
|
for (Module::const_global_iterator GV = M->global_begin(),E = M->global_end();
|
|
|
|
GV != E; ++GV) {
|
2007-04-24 00:04:05 +08:00
|
|
|
unsigned AbbrevToUse = 0;
|
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
// GLOBALVAR: [type, isconst, initid,
|
|
|
|
// linkage, alignment, section, visibility, threadlocal]
|
|
|
|
Vals.push_back(VE.getTypeID(GV->getType()));
|
|
|
|
Vals.push_back(GV->isConstant());
|
|
|
|
Vals.push_back(GV->isDeclaration() ? 0 :
|
|
|
|
(VE.getValueID(GV->getInitializer()) + 1));
|
|
|
|
Vals.push_back(getEncodedLinkage(GV));
|
|
|
|
Vals.push_back(Log2_32(GV->getAlignment())+1);
|
|
|
|
Vals.push_back(GV->hasSection() ? SectionMap[GV->getSection()] : 0);
|
2007-04-24 00:04:05 +08:00
|
|
|
if (GV->isThreadLocal() ||
|
|
|
|
GV->getVisibility() != GlobalValue::DefaultVisibility) {
|
|
|
|
Vals.push_back(getEncodedVisibility(GV));
|
|
|
|
Vals.push_back(GV->isThreadLocal());
|
|
|
|
} else {
|
|
|
|
AbbrevToUse = SimpleGVarAbbrev;
|
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
Stream.EmitRecord(bitc::MODULE_CODE_GLOBALVAR, Vals, AbbrevToUse);
|
|
|
|
Vals.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Emit the function proto information.
|
|
|
|
for (Module::const_iterator F = M->begin(), E = M->end(); F != E; ++F) {
|
2007-11-27 21:23:08 +08:00
|
|
|
// FUNCTION: [type, callingconv, isproto, paramattr,
|
2008-08-18 02:44:35 +08:00
|
|
|
// linkage, alignment, section, visibility, gc]
|
2007-04-22 14:24:45 +08:00
|
|
|
Vals.push_back(VE.getTypeID(F->getType()));
|
|
|
|
Vals.push_back(F->getCallingConv());
|
|
|
|
Vals.push_back(F->isDeclaration());
|
|
|
|
Vals.push_back(getEncodedLinkage(F));
|
2008-09-26 05:00:45 +08:00
|
|
|
Vals.push_back(VE.getAttributeID(F->getAttributes()));
|
2007-04-22 14:24:45 +08:00
|
|
|
Vals.push_back(Log2_32(F->getAlignment())+1);
|
|
|
|
Vals.push_back(F->hasSection() ? SectionMap[F->getSection()] : 0);
|
|
|
|
Vals.push_back(getEncodedVisibility(F));
|
2008-08-18 02:44:35 +08:00
|
|
|
Vals.push_back(F->hasGC() ? GCMap[F->getGC()] : 0);
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
unsigned AbbrevToUse = 0;
|
|
|
|
Stream.EmitRecord(bitc::MODULE_CODE_FUNCTION, Vals, AbbrevToUse);
|
|
|
|
Vals.clear();
|
|
|
|
}
|
2007-04-26 10:46:40 +08:00
|
|
|
|
|
|
|
|
|
|
|
// Emit the alias information.
|
|
|
|
for (Module::const_alias_iterator AI = M->alias_begin(), E = M->alias_end();
|
|
|
|
AI != E; ++AI) {
|
|
|
|
Vals.push_back(VE.getTypeID(AI->getType()));
|
|
|
|
Vals.push_back(VE.getValueID(AI->getAliasee()));
|
|
|
|
Vals.push_back(getEncodedLinkage(AI));
|
2008-03-12 05:40:17 +08:00
|
|
|
Vals.push_back(getEncodedVisibility(AI));
|
2007-04-26 10:46:40 +08:00
|
|
|
unsigned AbbrevToUse = 0;
|
|
|
|
Stream.EmitRecord(bitc::MODULE_CODE_ALIAS, Vals, AbbrevToUse);
|
|
|
|
Vals.clear();
|
|
|
|
}
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-04-24 08:16:04 +08:00
|
|
|
static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
|
|
|
const ValueEnumerator &VE,
|
2007-05-05 15:36:14 +08:00
|
|
|
BitstreamWriter &Stream, bool isGlobal) {
|
2007-04-24 08:16:04 +08:00
|
|
|
if (FirstVal == LastVal) return;
|
|
|
|
|
2007-05-05 15:36:14 +08:00
|
|
|
Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 4);
|
2007-04-24 04:35:01 +08:00
|
|
|
|
2007-05-05 15:36:14 +08:00
|
|
|
unsigned AggregateAbbrev = 0;
|
2007-05-06 08:53:07 +08:00
|
|
|
unsigned String8Abbrev = 0;
|
|
|
|
unsigned CString7Abbrev = 0;
|
|
|
|
unsigned CString6Abbrev = 0;
|
2009-04-04 15:22:01 +08:00
|
|
|
unsigned MDString8Abbrev = 0;
|
|
|
|
unsigned MDString6Abbrev = 0;
|
2007-05-05 15:36:14 +08:00
|
|
|
// If this is a constant pool for the module, emit module-specific abbrevs.
|
|
|
|
if (isGlobal) {
|
|
|
|
// Abbrev for CST_CODE_AGGREGATE.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_AGGREGATE));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, Log2_32_Ceil(LastVal+1)));
|
|
|
|
AggregateAbbrev = Stream.EmitAbbrev(Abbv);
|
2007-05-06 08:42:18 +08:00
|
|
|
|
|
|
|
// Abbrev for CST_CODE_STRING.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_STRING));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
2007-05-06 08:53:07 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
|
|
|
|
String8Abbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
// Abbrev for CST_CODE_CSTRING.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
2007-05-06 08:42:18 +08:00
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
|
2007-05-06 08:53:07 +08:00
|
|
|
CString7Abbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
// Abbrev for CST_CODE_CSTRING.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CSTRING));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
|
|
|
|
CString6Abbrev = Stream.EmitAbbrev(Abbv);
|
2009-04-04 15:22:01 +08:00
|
|
|
|
|
|
|
// Abbrev for CST_CODE_MDSTRING.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
|
|
|
|
MDString8Abbrev = Stream.EmitAbbrev(Abbv);
|
|
|
|
// Abbrev for CST_CODE_MDSTRING.
|
|
|
|
Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_MDSTRING));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
|
|
|
|
MDString6Abbrev = Stream.EmitAbbrev(Abbv);
|
2007-05-05 15:36:14 +08:00
|
|
|
}
|
|
|
|
|
2007-04-24 08:16:04 +08:00
|
|
|
SmallVector<uint64_t, 64> Record;
|
|
|
|
|
|
|
|
const ValueEnumerator::ValueList &Vals = VE.getValues();
|
|
|
|
const Type *LastTy = 0;
|
|
|
|
for (unsigned i = FirstVal; i != LastVal; ++i) {
|
|
|
|
const Value *V = Vals[i].first;
|
|
|
|
// If we need to switch types, do so now.
|
|
|
|
if (V->getType() != LastTy) {
|
|
|
|
LastTy = V->getType();
|
|
|
|
Record.push_back(VE.getTypeID(LastTy));
|
2007-05-05 15:36:14 +08:00
|
|
|
Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record,
|
|
|
|
CONSTANTS_SETTYPE_ABBREV);
|
2007-04-24 08:16:04 +08:00
|
|
|
Record.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
|
2007-05-06 09:58:20 +08:00
|
|
|
Record.push_back(unsigned(IA->hasSideEffects()));
|
|
|
|
|
|
|
|
// Add the asm string.
|
|
|
|
const std::string &AsmStr = IA->getAsmString();
|
|
|
|
Record.push_back(AsmStr.size());
|
|
|
|
for (unsigned i = 0, e = AsmStr.size(); i != e; ++i)
|
|
|
|
Record.push_back(AsmStr[i]);
|
|
|
|
|
|
|
|
// Add the constraint string.
|
|
|
|
const std::string &ConstraintStr = IA->getConstraintString();
|
|
|
|
Record.push_back(ConstraintStr.size());
|
|
|
|
for (unsigned i = 0, e = ConstraintStr.size(); i != e; ++i)
|
|
|
|
Record.push_back(ConstraintStr[i]);
|
|
|
|
Stream.EmitRecord(bitc::CST_CODE_INLINEASM, Record);
|
|
|
|
Record.clear();
|
2007-04-24 08:16:04 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const Constant *C = cast<Constant>(V);
|
|
|
|
unsigned Code = -1U;
|
|
|
|
unsigned AbbrevToUse = 0;
|
|
|
|
if (C->isNullValue()) {
|
|
|
|
Code = bitc::CST_CODE_NULL;
|
|
|
|
} else if (isa<UndefValue>(C)) {
|
|
|
|
Code = bitc::CST_CODE_UNDEF;
|
|
|
|
} else if (const ConstantInt *IV = dyn_cast<ConstantInt>(C)) {
|
|
|
|
if (IV->getBitWidth() <= 64) {
|
|
|
|
int64_t V = IV->getSExtValue();
|
|
|
|
if (V >= 0)
|
|
|
|
Record.push_back(V << 1);
|
|
|
|
else
|
|
|
|
Record.push_back((-V << 1) | 1);
|
|
|
|
Code = bitc::CST_CODE_INTEGER;
|
2007-05-05 15:36:14 +08:00
|
|
|
AbbrevToUse = CONSTANTS_INTEGER_ABBREV;
|
2007-04-24 08:16:04 +08:00
|
|
|
} else { // Wide integers, > 64 bits in size.
|
|
|
|
// 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.
|
|
|
|
unsigned NWords = IV->getValue().getActiveWords();
|
|
|
|
const uint64_t *RawWords = IV->getValue().getRawData();
|
|
|
|
for (unsigned i = 0; i != NWords; ++i) {
|
|
|
|
int64_t V = RawWords[i];
|
|
|
|
if (V >= 0)
|
|
|
|
Record.push_back(V << 1);
|
|
|
|
else
|
|
|
|
Record.push_back((-V << 1) | 1);
|
|
|
|
}
|
|
|
|
Code = bitc::CST_CODE_WIDE_INTEGER;
|
|
|
|
}
|
|
|
|
} else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C)) {
|
|
|
|
Code = bitc::CST_CODE_FLOAT;
|
2007-08-10 06:51:36 +08:00
|
|
|
const Type *Ty = CFP->getType();
|
2007-09-12 11:30:33 +08:00
|
|
|
if (Ty == Type::FloatTy || Ty == Type::DoubleTy) {
|
2008-10-10 02:53:47 +08:00
|
|
|
Record.push_back(CFP->getValueAPF().bitcastToAPInt().getZExtValue());
|
2007-09-12 02:32:33 +08:00
|
|
|
} else if (Ty == Type::X86_FP80Ty) {
|
2007-09-27 07:20:33 +08:00
|
|
|
// api needed to prevent premature destruction
|
2009-03-24 05:16:53 +08:00
|
|
|
// bits are not in the same order as a normal i80 APInt, compensate.
|
2008-10-10 02:53:47 +08:00
|
|
|
APInt api = CFP->getValueAPF().bitcastToAPInt();
|
2007-09-27 07:20:33 +08:00
|
|
|
const uint64_t *p = api.getRawData();
|
2009-03-24 05:16:53 +08:00
|
|
|
Record.push_back((p[1] << 48) | (p[0] >> 16));
|
|
|
|
Record.push_back(p[0] & 0xffffLL);
|
2007-10-12 02:07:22 +08:00
|
|
|
} else if (Ty == Type::FP128Ty || Ty == Type::PPC_FP128Ty) {
|
2008-10-10 02:53:47 +08:00
|
|
|
APInt api = CFP->getValueAPF().bitcastToAPInt();
|
2007-09-27 07:20:33 +08:00
|
|
|
const uint64_t *p = api.getRawData();
|
2007-09-12 02:32:33 +08:00
|
|
|
Record.push_back(p[0]);
|
|
|
|
Record.push_back(p[1]);
|
2007-08-10 06:51:36 +08:00
|
|
|
} else {
|
|
|
|
assert (0 && "Unknown FP type!");
|
2007-04-24 08:16:04 +08:00
|
|
|
}
|
2007-05-06 08:35:24 +08:00
|
|
|
} else if (isa<ConstantArray>(C) && cast<ConstantArray>(C)->isString()) {
|
|
|
|
// Emit constant strings specially.
|
2007-05-06 08:53:07 +08:00
|
|
|
unsigned NumOps = C->getNumOperands();
|
|
|
|
// If this is a null-terminated string, use the denser CSTRING encoding.
|
|
|
|
if (C->getOperand(NumOps-1)->isNullValue()) {
|
|
|
|
Code = bitc::CST_CODE_CSTRING;
|
|
|
|
--NumOps; // Don't encode the null, which isn't allowed by char6.
|
|
|
|
} else {
|
|
|
|
Code = bitc::CST_CODE_STRING;
|
|
|
|
AbbrevToUse = String8Abbrev;
|
|
|
|
}
|
|
|
|
bool isCStr7 = Code == bitc::CST_CODE_CSTRING;
|
|
|
|
bool isCStrChar6 = Code == bitc::CST_CODE_CSTRING;
|
|
|
|
for (unsigned i = 0; i != NumOps; ++i) {
|
2007-05-06 08:42:18 +08:00
|
|
|
unsigned char V = cast<ConstantInt>(C->getOperand(i))->getZExtValue();
|
|
|
|
Record.push_back(V);
|
2007-05-06 08:53:07 +08:00
|
|
|
isCStr7 &= (V & 128) == 0;
|
|
|
|
if (isCStrChar6)
|
|
|
|
isCStrChar6 = BitCodeAbbrevOp::isChar6(V);
|
2007-05-06 08:42:18 +08:00
|
|
|
}
|
2007-05-06 08:53:07 +08:00
|
|
|
|
|
|
|
if (isCStrChar6)
|
|
|
|
AbbrevToUse = CString6Abbrev;
|
|
|
|
else if (isCStr7)
|
|
|
|
AbbrevToUse = CString7Abbrev;
|
2007-04-24 08:16:04 +08:00
|
|
|
} else if (isa<ConstantArray>(C) || isa<ConstantStruct>(V) ||
|
|
|
|
isa<ConstantVector>(V)) {
|
|
|
|
Code = bitc::CST_CODE_AGGREGATE;
|
|
|
|
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(i)));
|
2007-05-05 15:36:14 +08:00
|
|
|
AbbrevToUse = AggregateAbbrev;
|
2007-04-24 08:16:04 +08:00
|
|
|
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
|
2007-04-24 15:07:11 +08:00
|
|
|
switch (CE->getOpcode()) {
|
|
|
|
default:
|
|
|
|
if (Instruction::isCast(CE->getOpcode())) {
|
|
|
|
Code = bitc::CST_CODE_CE_CAST;
|
|
|
|
Record.push_back(GetEncodedCastOpcode(CE->getOpcode()));
|
|
|
|
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
2007-05-05 15:36:14 +08:00
|
|
|
AbbrevToUse = CONSTANTS_CE_CAST_Abbrev;
|
2007-04-24 15:07:11 +08:00
|
|
|
} else {
|
|
|
|
assert(CE->getNumOperands() == 2 && "Unknown constant expr!");
|
|
|
|
Code = bitc::CST_CODE_CE_BINOP;
|
|
|
|
Record.push_back(GetEncodedBinaryOpcode(CE->getOpcode()));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::GetElementPtr:
|
|
|
|
Code = bitc::CST_CODE_CE_GEP;
|
|
|
|
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) {
|
|
|
|
Record.push_back(VE.getTypeID(C->getOperand(i)->getType()));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(i)));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Instruction::Select:
|
|
|
|
Code = bitc::CST_CODE_CE_SELECT;
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(2)));
|
|
|
|
break;
|
|
|
|
case Instruction::ExtractElement:
|
|
|
|
Code = bitc::CST_CODE_CE_EXTRACTELT;
|
|
|
|
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
break;
|
|
|
|
case Instruction::InsertElement:
|
|
|
|
Code = bitc::CST_CODE_CE_INSERTELT;
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(2)));
|
|
|
|
break;
|
|
|
|
case Instruction::ShuffleVector:
|
2009-02-13 05:28:33 +08:00
|
|
|
// If the return type and argument types are the same, this is a
|
|
|
|
// standard shufflevector instruction. If the types are different,
|
|
|
|
// then the shuffle is widening or truncating the input vectors, and
|
|
|
|
// the argument type must also be encoded.
|
|
|
|
if (C->getType() == C->getOperand(0)->getType()) {
|
|
|
|
Code = bitc::CST_CODE_CE_SHUFFLEVEC;
|
|
|
|
} else {
|
|
|
|
Code = bitc::CST_CODE_CE_SHUFVEC_EX;
|
|
|
|
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
|
|
|
}
|
2007-04-24 15:07:11 +08:00
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(2)));
|
|
|
|
break;
|
|
|
|
case Instruction::ICmp:
|
|
|
|
case Instruction::FCmp:
|
2008-05-13 03:01:56 +08:00
|
|
|
case Instruction::VICmp:
|
|
|
|
case Instruction::VFCmp:
|
2008-09-09 09:02:47 +08:00
|
|
|
if (isa<VectorType>(C->getOperand(0)->getType())
|
|
|
|
&& (CE->getOpcode() == Instruction::ICmp
|
|
|
|
|| CE->getOpcode() == Instruction::FCmp)) {
|
|
|
|
// compare returning vector of Int1Ty
|
|
|
|
assert(0 && "Unsupported constant!");
|
|
|
|
} else {
|
|
|
|
Code = bitc::CST_CODE_CE_CMP;
|
|
|
|
}
|
2007-04-24 15:07:11 +08:00
|
|
|
Record.push_back(VE.getTypeID(C->getOperand(0)->getType()));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(0)));
|
|
|
|
Record.push_back(VE.getValueID(C->getOperand(1)));
|
|
|
|
Record.push_back(CE->getPredicate());
|
|
|
|
break;
|
|
|
|
}
|
2009-04-04 15:22:01 +08:00
|
|
|
} else if (const MDString *S = dyn_cast<MDString>(C)) {
|
|
|
|
Code = bitc::CST_CODE_MDSTRING;
|
|
|
|
AbbrevToUse = MDString6Abbrev;
|
|
|
|
for (unsigned i = 0, e = S->size(); i != e; ++i) {
|
|
|
|
char V = S->begin()[i];
|
|
|
|
Record.push_back(V);
|
|
|
|
|
|
|
|
if (!BitCodeAbbrevOp::isChar6(V))
|
|
|
|
AbbrevToUse = MDString8Abbrev;
|
|
|
|
}
|
|
|
|
} else if (const MDNode *N = dyn_cast<MDNode>(C)) {
|
|
|
|
Code = bitc::CST_CODE_MDNODE;
|
2009-05-11 04:57:05 +08:00
|
|
|
for (unsigned i = 0, e = N->getNumElements(); i != e; ++i) {
|
|
|
|
if (N->getElement(i)) {
|
|
|
|
Record.push_back(VE.getTypeID(N->getElement(i)->getType()));
|
|
|
|
Record.push_back(VE.getValueID(N->getElement(i)));
|
|
|
|
} else {
|
|
|
|
Record.push_back(VE.getTypeID(Type::VoidTy));
|
|
|
|
Record.push_back(0);
|
|
|
|
}
|
2009-04-04 15:22:01 +08:00
|
|
|
}
|
2007-04-24 08:16:04 +08:00
|
|
|
} else {
|
|
|
|
assert(0 && "Unknown constant!");
|
|
|
|
}
|
|
|
|
Stream.EmitRecord(Code, Record, AbbrevToUse);
|
|
|
|
Record.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void WriteModuleConstants(const ValueEnumerator &VE,
|
|
|
|
BitstreamWriter &Stream) {
|
|
|
|
const ValueEnumerator::ValueList &Vals = VE.getValues();
|
|
|
|
|
|
|
|
// Find the first constant to emit, which is the first non-globalvalue value.
|
|
|
|
// We know globalvalues have been emitted by WriteModuleInfo.
|
|
|
|
for (unsigned i = 0, e = Vals.size(); i != e; ++i) {
|
|
|
|
if (!isa<GlobalValue>(Vals[i].first)) {
|
2007-05-05 15:36:14 +08:00
|
|
|
WriteConstants(i, Vals.size(), VE, Stream, true);
|
2007-04-24 08:16:04 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-04-24 04:35:01 +08:00
|
|
|
|
2007-05-06 08:00:00 +08:00
|
|
|
/// PushValueAndType - The file has to encode both the value and type id for
|
|
|
|
/// many values, because we need to know what type to create for forward
|
|
|
|
/// references. However, most operands are not forward references, so this type
|
|
|
|
/// field is not needed.
|
|
|
|
///
|
|
|
|
/// This function adds V's value ID to Vals. If the value ID is higher than the
|
|
|
|
/// instruction ID, then it is a forward reference, and it also includes the
|
|
|
|
/// type ID.
|
2009-01-17 02:40:27 +08:00
|
|
|
static bool PushValueAndType(const Value *V, unsigned InstID,
|
2007-05-06 08:00:00 +08:00
|
|
|
SmallVector<unsigned, 64> &Vals,
|
|
|
|
ValueEnumerator &VE) {
|
|
|
|
unsigned ValID = VE.getValueID(V);
|
|
|
|
Vals.push_back(ValID);
|
|
|
|
if (ValID >= InstID) {
|
|
|
|
Vals.push_back(VE.getTypeID(V->getType()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2007-04-26 13:53:54 +08:00
|
|
|
/// WriteInstruction - Emit an instruction to the specified stream.
|
2007-05-06 08:00:00 +08:00
|
|
|
static void WriteInstruction(const Instruction &I, unsigned InstID,
|
|
|
|
ValueEnumerator &VE, BitstreamWriter &Stream,
|
2007-04-26 13:53:54 +08:00
|
|
|
SmallVector<unsigned, 64> &Vals) {
|
|
|
|
unsigned Code = 0;
|
|
|
|
unsigned AbbrevToUse = 0;
|
|
|
|
switch (I.getOpcode()) {
|
|
|
|
default:
|
|
|
|
if (Instruction::isCast(I.getOpcode())) {
|
2007-05-01 10:13:26 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_CAST;
|
2007-05-06 10:38:57 +08:00
|
|
|
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
|
|
|
|
AbbrevToUse = FUNCTION_INST_CAST_ABBREV;
|
2007-04-26 13:53:54 +08:00
|
|
|
Vals.push_back(VE.getTypeID(I.getType()));
|
2007-05-06 08:21:25 +08:00
|
|
|
Vals.push_back(GetEncodedCastOpcode(I.getOpcode()));
|
2007-04-26 13:53:54 +08:00
|
|
|
} else {
|
|
|
|
assert(isa<BinaryOperator>(I) && "Unknown instruction!");
|
2007-05-02 12:26:36 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_BINOP;
|
2007-05-06 10:38:57 +08:00
|
|
|
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
|
|
|
|
AbbrevToUse = FUNCTION_INST_BINOP_ABBREV;
|
2007-04-26 13:53:54 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(1)));
|
2007-05-06 08:21:25 +08:00
|
|
|
Vals.push_back(GetEncodedBinaryOpcode(I.getOpcode()));
|
2007-04-26 13:53:54 +08:00
|
|
|
}
|
|
|
|
break;
|
2007-05-01 10:13:26 +08:00
|
|
|
|
|
|
|
case Instruction::GetElementPtr:
|
|
|
|
Code = bitc::FUNC_CODE_INST_GEP;
|
2007-05-06 08:00:00 +08:00
|
|
|
for (unsigned i = 0, e = I.getNumOperands(); i != e; ++i)
|
|
|
|
PushValueAndType(I.getOperand(i), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
break;
|
2008-06-01 03:11:15 +08:00
|
|
|
case Instruction::ExtractValue: {
|
2008-05-23 09:55:30 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_EXTRACTVAL;
|
2008-06-01 03:11:15 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
|
|
|
const ExtractValueInst *EVI = cast<ExtractValueInst>(&I);
|
|
|
|
for (const unsigned *i = EVI->idx_begin(), *e = EVI->idx_end(); i != e; ++i)
|
|
|
|
Vals.push_back(*i);
|
2008-05-23 09:55:30 +08:00
|
|
|
break;
|
2008-06-01 03:11:15 +08:00
|
|
|
}
|
|
|
|
case Instruction::InsertValue: {
|
2008-05-23 09:55:30 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_INSERTVAL;
|
2008-06-01 03:11:15 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
|
|
|
PushValueAndType(I.getOperand(1), InstID, Vals, VE);
|
|
|
|
const InsertValueInst *IVI = cast<InsertValueInst>(&I);
|
|
|
|
for (const unsigned *i = IVI->idx_begin(), *e = IVI->idx_end(); i != e; ++i)
|
|
|
|
Vals.push_back(*i);
|
2008-05-23 09:55:30 +08:00
|
|
|
break;
|
2008-06-01 03:11:15 +08:00
|
|
|
}
|
2007-05-01 10:13:26 +08:00
|
|
|
case Instruction::Select:
|
2008-09-16 09:01:33 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_VSELECT;
|
2007-05-06 08:21:25 +08:00
|
|
|
PushValueAndType(I.getOperand(1), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(2)));
|
2008-09-16 09:01:33 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
break;
|
|
|
|
case Instruction::ExtractElement:
|
|
|
|
Code = bitc::FUNC_CODE_INST_EXTRACTELT;
|
2007-05-06 08:21:25 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(1)));
|
|
|
|
break;
|
|
|
|
case Instruction::InsertElement:
|
|
|
|
Code = bitc::FUNC_CODE_INST_INSERTELT;
|
2007-05-06 08:21:25 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
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;
|
2007-05-06 08:21:25 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(1)));
|
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(2)));
|
|
|
|
break;
|
|
|
|
case Instruction::ICmp:
|
|
|
|
case Instruction::FCmp:
|
2008-05-13 03:01:56 +08:00
|
|
|
case Instruction::VICmp:
|
|
|
|
case Instruction::VFCmp:
|
2008-09-16 09:01:33 +08:00
|
|
|
if (I.getOpcode() == Instruction::ICmp
|
|
|
|
|| I.getOpcode() == Instruction::FCmp) {
|
|
|
|
// compare returning Int1Ty or vector of Int1Ty
|
|
|
|
Code = bitc::FUNC_CODE_INST_CMP2;
|
2008-09-09 09:02:47 +08:00
|
|
|
} else {
|
|
|
|
Code = bitc::FUNC_CODE_INST_CMP;
|
|
|
|
}
|
2007-05-06 08:00:00 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(1)));
|
|
|
|
Vals.push_back(cast<CmpInst>(I).getPredicate());
|
|
|
|
break;
|
|
|
|
|
2008-02-26 09:29:32 +08:00
|
|
|
case Instruction::Ret:
|
|
|
|
{
|
|
|
|
Code = bitc::FUNC_CODE_INST_RET;
|
|
|
|
unsigned NumOperands = I.getNumOperands();
|
|
|
|
if (NumOperands == 0)
|
|
|
|
AbbrevToUse = FUNCTION_INST_RET_VOID_ABBREV;
|
|
|
|
else if (NumOperands == 1) {
|
|
|
|
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE))
|
|
|
|
AbbrevToUse = FUNCTION_INST_RET_VAL_ABBREV;
|
|
|
|
} else {
|
|
|
|
for (unsigned i = 0, e = NumOperands; i != e; ++i)
|
|
|
|
PushValueAndType(I.getOperand(i), InstID, Vals, VE);
|
|
|
|
}
|
|
|
|
}
|
2007-05-01 10:13:26 +08:00
|
|
|
break;
|
|
|
|
case Instruction::Br:
|
2009-01-31 02:27:21 +08:00
|
|
|
{
|
|
|
|
Code = bitc::FUNC_CODE_INST_BR;
|
|
|
|
BranchInst &II(cast<BranchInst>(I));
|
|
|
|
Vals.push_back(VE.getValueID(II.getSuccessor(0)));
|
|
|
|
if (II.isConditional()) {
|
|
|
|
Vals.push_back(VE.getValueID(II.getSuccessor(1)));
|
|
|
|
Vals.push_back(VE.getValueID(II.getCondition()));
|
|
|
|
}
|
2007-05-01 10:13:26 +08:00
|
|
|
}
|
|
|
|
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;
|
2007-05-01 15:03:37 +08:00
|
|
|
case Instruction::Invoke: {
|
2009-01-17 02:40:27 +08:00
|
|
|
const InvokeInst *II = cast<InvokeInst>(&I);
|
|
|
|
const Value *Callee(II->getCalledValue());
|
|
|
|
const PointerType *PTy = cast<PointerType>(Callee->getType());
|
2007-05-08 13:38:01 +08:00
|
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
2007-05-01 10:13:26 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_INVOKE;
|
2007-05-08 13:38:01 +08:00
|
|
|
|
2008-09-26 05:00:45 +08:00
|
|
|
Vals.push_back(VE.getAttributeID(II->getAttributes()));
|
2007-11-27 21:23:08 +08:00
|
|
|
Vals.push_back(II->getCallingConv());
|
2009-01-08 06:39:29 +08:00
|
|
|
Vals.push_back(VE.getValueID(II->getNormalDest()));
|
|
|
|
Vals.push_back(VE.getValueID(II->getUnwindDest()));
|
2009-01-17 02:40:27 +08:00
|
|
|
PushValueAndType(Callee, InstID, Vals, VE);
|
2007-04-26 13:53:54 +08:00
|
|
|
|
2007-05-01 10:13:26 +08:00
|
|
|
// Emit value #'s for the fixed parameters.
|
|
|
|
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
|
2009-03-14 05:15:59 +08:00
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(i+3))); // fixed param.
|
2007-05-01 10:13:26 +08:00
|
|
|
|
|
|
|
// Emit type/value pairs for varargs params.
|
|
|
|
if (FTy->isVarArg()) {
|
2009-03-14 05:15:59 +08:00
|
|
|
for (unsigned i = 3+FTy->getNumParams(), e = I.getNumOperands();
|
2007-05-06 08:00:00 +08:00
|
|
|
i != e; ++i)
|
|
|
|
PushValueAndType(I.getOperand(i), InstID, Vals, VE); // vararg
|
2007-05-01 10:13:26 +08:00
|
|
|
}
|
|
|
|
break;
|
2007-05-01 15:03:37 +08:00
|
|
|
}
|
2007-04-26 13:53:54 +08:00
|
|
|
case Instruction::Unwind:
|
|
|
|
Code = bitc::FUNC_CODE_INST_UNWIND;
|
|
|
|
break;
|
|
|
|
case Instruction::Unreachable:
|
|
|
|
Code = bitc::FUNC_CODE_INST_UNREACHABLE;
|
2007-05-06 09:28:01 +08:00
|
|
|
AbbrevToUse = FUNCTION_INST_UNREACHABLE_ABBREV;
|
2007-04-26 13:53:54 +08:00
|
|
|
break;
|
2007-05-01 10:13:26 +08:00
|
|
|
|
|
|
|
case Instruction::PHI:
|
|
|
|
Code = bitc::FUNC_CODE_INST_PHI;
|
|
|
|
Vals.push_back(VE.getTypeID(I.getType()));
|
|
|
|
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;
|
2007-05-06 08:21:25 +08:00
|
|
|
PushValueAndType(I.getOperand(0), InstID, Vals, VE);
|
2007-05-01 10:13:26 +08:00
|
|
|
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;
|
2007-04-26 13:53:54 +08:00
|
|
|
|
2007-05-01 10:13:26 +08:00
|
|
|
case Instruction::Load:
|
|
|
|
Code = bitc::FUNC_CODE_INST_LOAD;
|
2007-05-06 08:00:00 +08:00
|
|
|
if (!PushValueAndType(I.getOperand(0), InstID, Vals, VE)) // ptr
|
|
|
|
AbbrevToUse = FUNCTION_INST_LOAD_ABBREV;
|
|
|
|
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(Log2_32(cast<LoadInst>(I).getAlignment())+1);
|
|
|
|
Vals.push_back(cast<LoadInst>(I).isVolatile());
|
|
|
|
break;
|
|
|
|
case Instruction::Store:
|
2007-12-11 16:59:05 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_STORE2;
|
|
|
|
PushValueAndType(I.getOperand(1), InstID, Vals, VE); // ptrty + ptr
|
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(0))); // val.
|
2007-05-01 10:13:26 +08:00
|
|
|
Vals.push_back(Log2_32(cast<StoreInst>(I).getAlignment())+1);
|
|
|
|
Vals.push_back(cast<StoreInst>(I).isVolatile());
|
|
|
|
break;
|
|
|
|
case Instruction::Call: {
|
2007-05-08 13:38:01 +08:00
|
|
|
const PointerType *PTy = cast<PointerType>(I.getOperand(0)->getType());
|
|
|
|
const FunctionType *FTy = cast<FunctionType>(PTy->getElementType());
|
|
|
|
|
2007-05-01 10:13:26 +08:00
|
|
|
Code = bitc::FUNC_CODE_INST_CALL;
|
2007-05-08 13:38:01 +08:00
|
|
|
|
2007-11-27 21:23:08 +08:00
|
|
|
const CallInst *CI = cast<CallInst>(&I);
|
2008-09-26 05:00:45 +08:00
|
|
|
Vals.push_back(VE.getAttributeID(CI->getAttributes()));
|
2007-11-27 21:23:08 +08:00
|
|
|
Vals.push_back((CI->getCallingConv() << 1) | unsigned(CI->isTailCall()));
|
|
|
|
PushValueAndType(CI->getOperand(0), InstID, Vals, VE); // Callee
|
2007-05-01 10:13:26 +08:00
|
|
|
|
|
|
|
// Emit value #'s for the fixed parameters.
|
|
|
|
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
|
|
|
|
Vals.push_back(VE.getValueID(I.getOperand(i+1))); // fixed param.
|
|
|
|
|
2007-05-01 15:03:37 +08:00
|
|
|
// 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();
|
2007-05-06 08:00:00 +08:00
|
|
|
i != e; ++i)
|
|
|
|
PushValueAndType(I.getOperand(i), InstID, Vals, VE); // varargs
|
2007-05-01 10:13:26 +08:00
|
|
|
}
|
|
|
|
break;
|
2007-05-01 15:03:37 +08:00
|
|
|
}
|
2007-05-01 10:13:26 +08:00
|
|
|
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;
|
2007-04-26 13:53:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Stream.EmitRecord(Code, Vals, AbbrevToUse);
|
|
|
|
Vals.clear();
|
|
|
|
}
|
|
|
|
|
2007-05-01 10:14:57 +08:00
|
|
|
// Emit names for globals/functions etc.
|
|
|
|
static void WriteValueSymbolTable(const ValueSymbolTable &VST,
|
|
|
|
const ValueEnumerator &VE,
|
|
|
|
BitstreamWriter &Stream) {
|
|
|
|
if (VST.empty()) return;
|
2007-05-05 09:26:50 +08:00
|
|
|
Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 4);
|
2007-05-05 04:34:50 +08:00
|
|
|
|
2007-05-01 10:14:57 +08:00
|
|
|
// 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) {
|
2007-05-05 04:52:02 +08:00
|
|
|
|
|
|
|
const ValueName &Name = *SI;
|
|
|
|
|
|
|
|
// Figure out the encoding to use for the name.
|
|
|
|
bool is7Bit = true;
|
2007-05-05 09:26:50 +08:00
|
|
|
bool isChar6 = true;
|
|
|
|
for (const char *C = Name.getKeyData(), *E = C+Name.getKeyLength();
|
|
|
|
C != E; ++C) {
|
|
|
|
if (isChar6)
|
|
|
|
isChar6 = BitCodeAbbrevOp::isChar6(*C);
|
|
|
|
if ((unsigned char)*C & 128) {
|
2007-05-05 04:52:02 +08:00
|
|
|
is7Bit = false;
|
2007-05-05 09:26:50 +08:00
|
|
|
break; // don't bother scanning the rest.
|
2007-05-05 04:52:02 +08:00
|
|
|
}
|
2007-05-05 09:26:50 +08:00
|
|
|
}
|
2007-05-05 04:52:02 +08:00
|
|
|
|
2007-05-05 05:31:13 +08:00
|
|
|
unsigned AbbrevToUse = VST_ENTRY_8_ABBREV;
|
2007-05-01 10:14:57 +08:00
|
|
|
|
2007-05-05 05:31:13 +08:00
|
|
|
// VST_ENTRY: [valueid, namechar x N]
|
|
|
|
// VST_BBENTRY: [bbid, namechar x N]
|
2007-05-04 06:18:21 +08:00
|
|
|
unsigned Code;
|
|
|
|
if (isa<BasicBlock>(SI->getValue())) {
|
|
|
|
Code = bitc::VST_CODE_BBENTRY;
|
2007-05-05 09:26:50 +08:00
|
|
|
if (isChar6)
|
|
|
|
AbbrevToUse = VST_BBENTRY_6_ABBREV;
|
2007-05-04 06:18:21 +08:00
|
|
|
} else {
|
|
|
|
Code = bitc::VST_CODE_ENTRY;
|
2007-05-05 09:26:50 +08:00
|
|
|
if (isChar6)
|
|
|
|
AbbrevToUse = VST_ENTRY_6_ABBREV;
|
|
|
|
else if (is7Bit)
|
|
|
|
AbbrevToUse = VST_ENTRY_7_ABBREV;
|
2007-05-04 06:18:21 +08:00
|
|
|
}
|
2007-05-01 10:14:57 +08:00
|
|
|
|
2007-05-04 06:18:21 +08:00
|
|
|
NameVals.push_back(VE.getValueID(SI->getValue()));
|
2007-05-05 04:52:02 +08:00
|
|
|
for (const char *P = Name.getKeyData(),
|
|
|
|
*E = Name.getKeyData()+Name.getKeyLength(); P != E; ++P)
|
2007-05-01 10:14:57 +08:00
|
|
|
NameVals.push_back((unsigned char)*P);
|
|
|
|
|
|
|
|
// Emit the finished record.
|
2007-05-04 06:18:21 +08:00
|
|
|
Stream.EmitRecord(Code, NameVals, AbbrevToUse);
|
2007-05-01 10:14:57 +08:00
|
|
|
NameVals.clear();
|
|
|
|
}
|
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
2007-04-26 11:50:57 +08:00
|
|
|
/// WriteFunction - Emit a function body to the module stream.
|
2007-04-26 11:27:58 +08:00
|
|
|
static void WriteFunction(const Function &F, ValueEnumerator &VE,
|
|
|
|
BitstreamWriter &Stream) {
|
2007-05-06 10:38:57 +08:00
|
|
|
Stream.EnterSubblock(bitc::FUNCTION_BLOCK_ID, 4);
|
2007-04-26 11:50:57 +08:00
|
|
|
VE.incorporateFunction(F);
|
2007-04-26 13:53:54 +08:00
|
|
|
|
|
|
|
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();
|
|
|
|
|
|
|
|
// If there are function-local constants, emit them now.
|
|
|
|
unsigned CstStart, CstEnd;
|
|
|
|
VE.getFunctionConstantRange(CstStart, CstEnd);
|
2007-05-05 15:36:14 +08:00
|
|
|
WriteConstants(CstStart, CstEnd, VE, Stream, false);
|
2007-04-26 13:53:54 +08:00
|
|
|
|
2007-05-06 08:00:00 +08:00
|
|
|
// Keep a running idea of what the instruction ID is.
|
|
|
|
unsigned InstID = CstEnd;
|
|
|
|
|
2007-04-26 13:53:54 +08:00
|
|
|
// Finally, emit all the instructions, in order.
|
2008-04-26 00:53:59 +08:00
|
|
|
for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
|
2007-05-06 08:00:00 +08:00
|
|
|
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
|
|
|
|
I != E; ++I) {
|
|
|
|
WriteInstruction(*I, InstID, VE, Stream, Vals);
|
|
|
|
if (I->getType() != Type::VoidTy)
|
|
|
|
++InstID;
|
|
|
|
}
|
2007-04-26 11:27:58 +08:00
|
|
|
|
2007-05-01 10:14:57 +08:00
|
|
|
// Emit names for all the instructions etc.
|
|
|
|
WriteValueSymbolTable(F.getValueSymbolTable(), VE, Stream);
|
|
|
|
|
2007-04-26 11:50:57 +08:00
|
|
|
VE.purgeFunction();
|
2007-04-26 13:53:54 +08:00
|
|
|
Stream.ExitBlock();
|
2007-04-26 11:27:58 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// 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);
|
|
|
|
|
2007-05-05 08:47:19 +08:00
|
|
|
// 7-bit fixed width VST_CODE_ENTRY strings.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
|
|
|
|
unsigned V7Abbrev = Stream.EmitAbbrev(Abbv);
|
2007-04-26 11:27:58 +08:00
|
|
|
|
|
|
|
SmallVector<unsigned, 64> NameVals;
|
|
|
|
|
|
|
|
for (TypeSymbolTable::const_iterator TI = TST.begin(), TE = TST.end();
|
|
|
|
TI != TE; ++TI) {
|
2007-05-05 08:47:19 +08:00
|
|
|
// TST_ENTRY: [typeid, namechar x N]
|
2007-04-26 11:27:58 +08:00
|
|
|
NameVals.push_back(VE.getTypeID(TI->second));
|
|
|
|
|
|
|
|
const std::string &Str = TI->first;
|
2007-05-05 08:47:19 +08:00
|
|
|
bool is7Bit = true;
|
|
|
|
for (unsigned i = 0, e = Str.size(); i != e; ++i) {
|
|
|
|
NameVals.push_back((unsigned char)Str[i]);
|
|
|
|
if (Str[i] & 128)
|
|
|
|
is7Bit = false;
|
|
|
|
}
|
2007-04-26 11:27:58 +08:00
|
|
|
|
|
|
|
// Emit the finished record.
|
2007-05-05 08:47:19 +08:00
|
|
|
Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, is7Bit ? V7Abbrev : 0);
|
2007-04-26 11:27:58 +08:00
|
|
|
NameVals.clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
2007-05-05 15:36:14 +08:00
|
|
|
// Emit blockinfo, which defines the standard abbreviations etc.
|
|
|
|
static void WriteBlockInfo(const ValueEnumerator &VE, BitstreamWriter &Stream) {
|
|
|
|
// We only want to emit block info records for blocks that have multiple
|
|
|
|
// instances: CONSTANTS_BLOCK, FUNCTION_BLOCK and VALUE_SYMTAB_BLOCK. Other
|
|
|
|
// blocks can defined their abbrevs inline.
|
|
|
|
Stream.EnterBlockInfoBlock(2);
|
|
|
|
|
|
|
|
{ // 8-bit fixed-width VST_ENTRY/VST_BBENTRY strings.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 8));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
|
|
|
|
Abbv) != VST_ENTRY_8_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
|
|
|
{ // 7-bit fixed width VST_ENTRY strings.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
|
|
|
|
Abbv) != VST_ENTRY_7_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // 6-bit char6 VST_ENTRY strings.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
|
|
|
|
Abbv) != VST_ENTRY_6_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // 6-bit char6 VST_BBENTRY strings.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_BBENTRY));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Char6));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::VALUE_SYMTAB_BLOCK_ID,
|
|
|
|
Abbv) != VST_BBENTRY_6_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
2007-05-05 15:44:49 +08:00
|
|
|
|
|
|
|
|
2007-05-05 15:36:14 +08:00
|
|
|
{ // SETTYPE abbrev for CONSTANTS_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_SETTYPE));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed,
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
|
|
|
|
Abbv) != CONSTANTS_SETTYPE_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
|
|
|
{ // INTEGER abbrev for CONSTANTS_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_INTEGER));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
|
|
|
|
Abbv) != CONSTANTS_INTEGER_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
|
|
|
{ // CE_CAST abbrev for CONSTANTS_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_CE_CAST));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // cast opc
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // typeid
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8)); // value id
|
|
|
|
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
|
|
|
|
Abbv) != CONSTANTS_CE_CAST_Abbrev)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // NULL abbrev for CONSTANTS_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::CST_CODE_NULL));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::CONSTANTS_BLOCK_ID,
|
|
|
|
Abbv) != CONSTANTS_NULL_Abbrev)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
2007-05-05 15:44:49 +08:00
|
|
|
// FIXME: This should only use space for first class types!
|
|
|
|
|
|
|
|
{ // INST_LOAD abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_LOAD));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Ptr
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 4)); // Align
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // volatile
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_LOAD_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
2007-05-06 10:38:57 +08:00
|
|
|
{ // INST_BINOP abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_BINOP));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHS
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // RHS
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_BINOP_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // INST_CAST abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_CAST));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpVal
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, // dest ty
|
|
|
|
Log2_32_Ceil(VE.getTypes().size()+1)));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 4)); // opc
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_CAST_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
|
2007-05-06 09:28:01 +08:00
|
|
|
{ // INST_RET abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_RET_VOID_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // INST_RET abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_RET));
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ValID
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_RET_VAL_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
|
|
|
{ // INST_UNREACHABLE abbrev for FUNCTION_BLOCK.
|
|
|
|
BitCodeAbbrev *Abbv = new BitCodeAbbrev();
|
|
|
|
Abbv->Add(BitCodeAbbrevOp(bitc::FUNC_CODE_INST_UNREACHABLE));
|
|
|
|
if (Stream.EmitBlockInfoAbbrev(bitc::FUNCTION_BLOCK_ID,
|
|
|
|
Abbv) != FUNCTION_INST_UNREACHABLE_ABBREV)
|
|
|
|
assert(0 && "Unexpected abbrev ordering!");
|
|
|
|
}
|
2007-05-05 15:44:49 +08:00
|
|
|
|
2007-05-05 15:36:14 +08:00
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
2007-04-26 11:27:58 +08:00
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
/// WriteModule - Emit the specified module to the bitstream.
|
|
|
|
static void WriteModule(const Module *M, BitstreamWriter &Stream) {
|
2007-04-24 02:58:34 +08:00
|
|
|
Stream.EnterSubblock(bitc::MODULE_BLOCK_ID, 3);
|
2007-04-22 14:24:45 +08:00
|
|
|
|
|
|
|
// Emit the version number if it is non-zero.
|
|
|
|
if (CurVersion) {
|
2007-04-26 11:27:58 +08:00
|
|
|
SmallVector<unsigned, 1> Vals;
|
|
|
|
Vals.push_back(CurVersion);
|
|
|
|
Stream.EmitRecord(bitc::MODULE_CODE_VERSION, Vals);
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Analyze the module, enumerating globals, functions, etc.
|
|
|
|
ValueEnumerator VE(M);
|
2007-05-05 15:36:14 +08:00
|
|
|
|
|
|
|
// Emit blockinfo, which defines the standard abbreviations etc.
|
|
|
|
WriteBlockInfo(VE, Stream);
|
2007-04-22 14:24:45 +08:00
|
|
|
|
2007-05-04 08:44:52 +08:00
|
|
|
// Emit information about parameter attributes.
|
2008-09-26 05:00:45 +08:00
|
|
|
WriteAttributeTable(VE, Stream);
|
2007-05-04 08:44:52 +08:00
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
// Emit information describing all of the types in the module.
|
|
|
|
WriteTypeTable(VE, Stream);
|
|
|
|
|
|
|
|
// Emit top-level description of module, including target triple, inline asm,
|
|
|
|
// descriptors for global variables, and function prototype info.
|
|
|
|
WriteModuleInfo(M, VE, Stream);
|
|
|
|
|
2007-04-24 08:16:04 +08:00
|
|
|
// Emit constants.
|
|
|
|
WriteModuleConstants(VE, Stream);
|
|
|
|
|
2007-04-26 11:27:58 +08:00
|
|
|
// Emit function bodies.
|
|
|
|
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
|
2007-04-26 11:32:43 +08:00
|
|
|
if (!I->isDeclaration())
|
|
|
|
WriteFunction(*I, VE, Stream);
|
2007-04-26 11:27:58 +08:00
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
// Emit the type symbol table information.
|
|
|
|
WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
|
2007-04-24 04:35:01 +08:00
|
|
|
|
|
|
|
// Emit names for globals/functions etc.
|
|
|
|
WriteValueSymbolTable(M->getValueSymbolTable(), VE, Stream);
|
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
Stream.ExitBlock();
|
|
|
|
}
|
|
|
|
|
2008-07-09 13:14:23 +08:00
|
|
|
/// EmitDarwinBCHeader - If generating a bc file on darwin, we have to emit a
|
|
|
|
/// header and trailer to make it compatible with the system archiver. To do
|
|
|
|
/// this we emit the following header, and then emit a trailer that pads the
|
|
|
|
/// file out to be a multiple of 16 bytes.
|
|
|
|
///
|
|
|
|
/// struct bc_header {
|
|
|
|
/// uint32_t Magic; // 0x0B17C0DE
|
|
|
|
/// uint32_t Version; // Version, currently always 0.
|
|
|
|
/// uint32_t BitcodeOffset; // Offset to traditional bitcode file.
|
|
|
|
/// uint32_t BitcodeSize; // Size of traditional bitcode file.
|
|
|
|
/// uint32_t CPUType; // CPU specifier.
|
|
|
|
/// ... potentially more later ...
|
|
|
|
/// };
|
|
|
|
enum {
|
|
|
|
DarwinBCSizeFieldOffset = 3*4, // Offset to bitcode_size.
|
|
|
|
DarwinBCHeaderSize = 5*4
|
|
|
|
};
|
|
|
|
|
|
|
|
static void EmitDarwinBCHeader(BitstreamWriter &Stream,
|
|
|
|
const std::string &TT) {
|
|
|
|
unsigned CPUType = ~0U;
|
|
|
|
|
|
|
|
// Match x86_64-*, i[3-9]86-*, powerpc-*, powerpc64-*. The CPUType is a
|
|
|
|
// magic number from /usr/include/mach/machine.h. It is ok to reproduce the
|
|
|
|
// specific constants here because they are implicitly part of the Darwin ABI.
|
|
|
|
enum {
|
|
|
|
DARWIN_CPU_ARCH_ABI64 = 0x01000000,
|
|
|
|
DARWIN_CPU_TYPE_X86 = 7,
|
|
|
|
DARWIN_CPU_TYPE_POWERPC = 18
|
|
|
|
};
|
|
|
|
|
|
|
|
if (TT.find("x86_64-") == 0)
|
|
|
|
CPUType = DARWIN_CPU_TYPE_X86 | DARWIN_CPU_ARCH_ABI64;
|
|
|
|
else if (TT.size() >= 5 && TT[0] == 'i' && TT[2] == '8' && TT[3] == '6' &&
|
|
|
|
TT[4] == '-' && TT[1] - '3' < 6)
|
|
|
|
CPUType = DARWIN_CPU_TYPE_X86;
|
|
|
|
else if (TT.find("powerpc-") == 0)
|
|
|
|
CPUType = DARWIN_CPU_TYPE_POWERPC;
|
|
|
|
else if (TT.find("powerpc64-") == 0)
|
|
|
|
CPUType = DARWIN_CPU_TYPE_POWERPC | DARWIN_CPU_ARCH_ABI64;
|
|
|
|
|
|
|
|
// Traditional Bitcode starts after header.
|
|
|
|
unsigned BCOffset = DarwinBCHeaderSize;
|
|
|
|
|
|
|
|
Stream.Emit(0x0B17C0DE, 32);
|
|
|
|
Stream.Emit(0 , 32); // Version.
|
|
|
|
Stream.Emit(BCOffset , 32);
|
|
|
|
Stream.Emit(0 , 32); // Filled in later.
|
|
|
|
Stream.Emit(CPUType , 32);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// EmitDarwinBCTrailer - Emit the darwin epilog after the bitcode file and
|
|
|
|
/// finalize the header.
|
|
|
|
static void EmitDarwinBCTrailer(BitstreamWriter &Stream, unsigned BufferSize) {
|
|
|
|
// Update the size field in the header.
|
|
|
|
Stream.BackpatchWord(DarwinBCSizeFieldOffset, BufferSize-DarwinBCHeaderSize);
|
|
|
|
|
|
|
|
// If the file is not a multiple of 16 bytes, insert dummy padding.
|
|
|
|
while (BufferSize & 15) {
|
|
|
|
Stream.Emit(0, 8);
|
|
|
|
++BufferSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-05 02:26:27 +08:00
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
/// WriteBitcodeToFile - Write the specified module to the specified output
|
|
|
|
/// stream.
|
|
|
|
void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) {
|
2008-10-23 01:39:14 +08:00
|
|
|
raw_os_ostream RawOut(Out);
|
2008-10-24 03:37:34 +08:00
|
|
|
// If writing to stdout, set binary mode.
|
|
|
|
if (llvm::cout == Out)
|
|
|
|
sys::Program::ChangeStdoutToBinary();
|
2008-10-23 01:39:14 +08:00
|
|
|
WriteBitcodeToFile(M, RawOut);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// WriteBitcodeToFile - Write the specified module to the specified output
|
|
|
|
/// stream.
|
|
|
|
void llvm::WriteBitcodeToFile(const Module *M, raw_ostream &Out) {
|
2007-04-22 14:24:45 +08:00
|
|
|
std::vector<unsigned char> Buffer;
|
|
|
|
BitstreamWriter Stream(Buffer);
|
|
|
|
|
|
|
|
Buffer.reserve(256*1024);
|
2008-12-20 02:37:59 +08:00
|
|
|
|
|
|
|
WriteBitcodeToStream( M, Stream );
|
|
|
|
|
|
|
|
// If writing to stdout, set binary mode.
|
|
|
|
if (&llvm::outs() == &Out)
|
|
|
|
sys::Program::ChangeStdoutToBinary();
|
|
|
|
|
|
|
|
// Write the generated bitstream to "Out".
|
|
|
|
Out.write((char*)&Buffer.front(), Buffer.size());
|
2007-04-22 14:24:45 +08:00
|
|
|
|
2008-12-20 02:37:59 +08:00
|
|
|
// Make sure it hits disk now.
|
|
|
|
Out.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
/// WriteBitcodeToStream - Write the specified module to the specified output
|
|
|
|
/// stream.
|
|
|
|
void llvm::WriteBitcodeToStream(const Module *M, BitstreamWriter &Stream) {
|
2008-07-09 13:14:23 +08:00
|
|
|
// If this is darwin, emit a file header and trailer if needed.
|
|
|
|
bool isDarwin = M->getTargetTriple().find("-darwin") != std::string::npos;
|
|
|
|
if (isDarwin)
|
|
|
|
EmitDarwinBCHeader(Stream, M->getTargetTriple());
|
|
|
|
|
2007-04-22 14:24:45 +08:00
|
|
|
// Emit the file header.
|
|
|
|
Stream.Emit((unsigned)'B', 8);
|
|
|
|
Stream.Emit((unsigned)'C', 8);
|
|
|
|
Stream.Emit(0x0, 4);
|
|
|
|
Stream.Emit(0xC, 4);
|
|
|
|
Stream.Emit(0xE, 4);
|
|
|
|
Stream.Emit(0xD, 4);
|
|
|
|
|
|
|
|
// Emit the module.
|
|
|
|
WriteModule(M, Stream);
|
2008-07-09 13:14:23 +08:00
|
|
|
|
|
|
|
if (isDarwin)
|
2008-12-20 02:37:59 +08:00
|
|
|
EmitDarwinBCTrailer(Stream, Stream.getBuffer().size());
|
2007-04-22 14:24:45 +08:00
|
|
|
}
|