#include "llvm/DerivedTypes.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
+#include "llvm/ParameterAttributes.h"
#include "llvm/TypeSymbolTable.h"
#include "llvm/ValueSymbolTable.h"
#include "llvm/Support/MathExtras.h"
unsigned AbbrevToUse, BitstreamWriter &Stream) {
SmallVector<unsigned, 64> Vals;
- // Code: [strlen, strchar x N]
- Vals.push_back(Str.size());
+ // Code: [strchar x N]
for (unsigned i = 0, e = Str.size(); i != e; ++i)
Vals.push_back(Str[i]);
Stream.EmitRecord(Code, Vals, AbbrevToUse);
}
+// Emit information about parameter attributes.
+static void WriteParamAttrTable(const ValueEnumerator &VE,
+ BitstreamWriter &Stream) {
+ const std::vector<const ParamAttrsList*> &Attrs = VE.getParamAttrs();
+ if (Attrs.empty()) return;
+
+ Stream.EnterSubblock(bitc::PARAMATTR_BLOCK_ID, 3);
+
+ SmallVector<uint64_t, 64> Record;
+ for (unsigned i = 0, e = Attrs.size(); i != e; ++i) {
+ const ParamAttrsList *A = Attrs[i];
+ for (unsigned op = 0, e = A->size(); op != e; ++op) {
+ Record.push_back(A->getParamIndex(op));
+ Record.push_back(A->getParamAttrsAtIndex(op));
+ }
+
+ Stream.EmitRecord(bitc::PARAMATTR_CODE_ENTRY, Record);
+ Record.clear();
+ }
+
+ Stream.ExitBlock();
+}
/// WriteTypeTable - Write out the type table for a module.
static void WriteTypeTable(const ValueEnumerator &VE, BitstreamWriter &Stream) {
case Type::FunctionTyID: {
const FunctionType *FT = cast<FunctionType>(T);
- // FUNCTION: [isvararg, #pararms, paramty x N]
+ // FUNCTION: [isvararg, attrid, #pararms, paramty x N]
Code = bitc::TYPE_CODE_FUNCTION;
TypeVals.push_back(FT->isVarArg());
+ TypeVals.push_back(VE.getParamAttrID(FT->getParamAttrs()));
TypeVals.push_back(VE.getTypeID(FT->getReturnType()));
- // FIXME: PARAM ATTR ID!
- TypeVals.push_back(FT->getNumParams());
for (unsigned i = 0, e = FT->getNumParams(); i != e; ++i)
TypeVals.push_back(VE.getTypeID(FT->getParamType(i)));
break;
// STRUCT: [ispacked, #elts, eltty x N]
Code = bitc::TYPE_CODE_STRUCT;
TypeVals.push_back(ST->isPacked());
- TypeVals.push_back(ST->getNumElements());
- // Output all of the element types...
+ // Output all of the element types.
for (StructType::element_iterator I = ST->element_begin(),
E = ST->element_end(); I != E; ++I)
TypeVals.push_back(VE.getTypeID(*I));
// So, we only write the number of active words.
unsigned NWords = IV->getValue().getActiveWords();
const uint64_t *RawWords = IV->getValue().getRawData();
- Record.push_back(NWords);
for (unsigned i = 0; i != NWords; ++i) {
int64_t V = RawWords[i];
if (V >= 0)
} else if (isa<ConstantArray>(C) || isa<ConstantStruct>(V) ||
isa<ConstantVector>(V)) {
Code = bitc::CST_CODE_AGGREGATE;
- Record.push_back(C->getNumOperands());
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i)
Record.push_back(VE.getValueID(C->getOperand(i)));
} else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
break;
case Instruction::GetElementPtr:
Code = bitc::CST_CODE_CE_GEP;
- Record.push_back(CE->getNumOperands());
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::Invoke: {
Code = bitc::FUNC_CODE_INST_INVOKE;
- // FIXME: param attrs
+ 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
// 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()));
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;
break;
case Instruction::Call: {
Code = bitc::FUNC_CODE_INST_CALL;
- // FIXME: param attrs
+ 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 type/value pairs for varargs params.
if (FTy->isVarArg()) {
unsigned NumVarargs = I.getNumOperands()-1-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()));
if (VST.empty()) return;
Stream.EnterSubblock(bitc::VALUE_SYMTAB_BLOCK_ID, 3);
+#if 0
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::VST_ENTRY));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth,
+ Log2_32_Ceil(MaxGlobalType+1)));
+ // Don't bother emitting vis + thread local.
+ SimpleGVarAbbrev = Stream.EmitAbbrev(Abbv);
+#endif
+
+
// 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;
}
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);
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]);
// Analyze the module, enumerating globals, functions, etc.
ValueEnumerator VE(M);
+ // Emit information about parameter attributes.
+ WriteParamAttrTable(VE, Stream);
+
// Emit information describing all of the types in the module.
WriteTypeTable(VE, Stream);
Stream.ExitBlock();
}
+// Emit blockinfo, which defines the standard abbreviations etc.
+static void WriteBlockInfo(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.EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, 2);
+
+#if 0
+ // Configure TYPE_SYMTAB_BLOCK's.
+
+ // Add an abbrev for VST_ENTRY where the characters each fit in 7 bits.
+ BitCodeAbbrev *Abbv = new BitCodeAbbrev();
+ Abbv->Add(BitCodeAbbrevOp(bitc::VST_CODE_ENTRY));
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 8); // Value ID
+ Abbv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::FixedWidth, 3)); // Linkage.
+
+ xxx = Stream.EmitAbbrev(Abbv);
+#endif
+ Stream.ExitBlock();
+}
+
+
/// WriteBitcodeToFile - Write the specified module to the specified output
/// stream.
void llvm::WriteBitcodeToFile(const Module *M, std::ostream &Out) {
Stream.Emit(0xE, 4);
Stream.Emit(0xD, 4);
+ // Emit blockinfo, which defines the standard abbreviations etc.
+ WriteBlockInfo(Stream);
+
// Emit the module.
WriteModule(M, Stream);