mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-01 15:40:46 +00:00
Emit module-level constants.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36384 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
00d56b96e5
commit
2edd22b959
@ -15,6 +15,7 @@
|
||||
#include "llvm/Bitcode/BitstreamWriter.h"
|
||||
#include "llvm/Bitcode/LLVMBitCodes.h"
|
||||
#include "ValueEnumerator.h"
|
||||
#include "llvm/Constants.h"
|
||||
#include "llvm/DerivedTypes.h"
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/TypeSymbolTable.h"
|
||||
@ -296,7 +297,7 @@ static void WriteTypeSymbolTable(const TypeSymbolTable &TST,
|
||||
NameVals.push_back(Str[i]);
|
||||
|
||||
// Emit the finished record.
|
||||
Stream.EmitRecord(bitc::TST_ENTRY_CODE, NameVals, AbbrevToUse);
|
||||
Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, AbbrevToUse);
|
||||
NameVals.clear();
|
||||
}
|
||||
|
||||
@ -327,13 +328,118 @@ static void WriteValueSymbolTable(const ValueSymbolTable &VST,
|
||||
NameVals.push_back((unsigned char)*P);
|
||||
|
||||
// Emit the finished record.
|
||||
Stream.EmitRecord(bitc::VST_ENTRY_CODE, NameVals, AbbrevToUse);
|
||||
Stream.EmitRecord(bitc::VST_CODE_ENTRY, NameVals, AbbrevToUse);
|
||||
NameVals.clear();
|
||||
}
|
||||
Stream.ExitBlock();
|
||||
}
|
||||
|
||||
static void WriteConstants(unsigned FirstVal, unsigned LastVal,
|
||||
const ValueEnumerator &VE,
|
||||
BitstreamWriter &Stream) {
|
||||
if (FirstVal == LastVal) return;
|
||||
|
||||
Stream.EnterSubblock(bitc::CONSTANTS_BLOCK_ID, 2);
|
||||
|
||||
// FIXME: Install and use abbrevs to reduce size.
|
||||
|
||||
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));
|
||||
Stream.EmitRecord(bitc::CST_CODE_SETTYPE, Record);
|
||||
Record.clear();
|
||||
}
|
||||
|
||||
if (const InlineAsm *IA = dyn_cast<InlineAsm>(V)) {
|
||||
assert(0 && IA && "FIXME: Inline asm writing unimp!");
|
||||
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;
|
||||
} 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();
|
||||
Record.push_back(NWords);
|
||||
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;
|
||||
if (CFP->getType() == Type::FloatTy) {
|
||||
Record.push_back(FloatToBits((float)CFP->getValue()));
|
||||
} else {
|
||||
assert (CFP->getType() == Type::DoubleTy && "Unknown FP type!");
|
||||
Record.push_back(DoubleToBits((double)CFP->getValue()));
|
||||
}
|
||||
} 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)) {
|
||||
Code = bitc::CST_CODE_CONSTEXPR;
|
||||
// FIXME: optimize for binops, compares, etc.
|
||||
Record.push_back(CE->getOpcode());
|
||||
Record.push_back(CE->getNumOperands());
|
||||
for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
|
||||
Record.push_back(VE.getValueID(C->getOperand(i)));
|
||||
// Compares also pass their predicate.
|
||||
if (CE->isCompare())
|
||||
Record.push_back((unsigned)CE->getPredicate());
|
||||
} 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)) {
|
||||
WriteConstants(i, Vals.size(), VE, Stream);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// WriteModule - Emit the specified module to the bitstream.
|
||||
static void WriteModule(const Module *M, BitstreamWriter &Stream) {
|
||||
@ -352,12 +458,13 @@ static void WriteModule(const Module *M, BitstreamWriter &Stream) {
|
||||
// Emit information describing all of the types in the module.
|
||||
WriteTypeTable(VE, Stream);
|
||||
|
||||
// FIXME: Emit constants.
|
||||
|
||||
// Emit top-level description of module, including target triple, inline asm,
|
||||
// descriptors for global variables, and function prototype info.
|
||||
WriteModuleInfo(M, VE, Stream);
|
||||
|
||||
// Emit constants.
|
||||
WriteModuleConstants(VE, Stream);
|
||||
|
||||
// Emit the type symbol table information.
|
||||
WriteTypeSymbolTable(M->getTypeSymbolTable(), VE, Stream);
|
||||
|
||||
|
@ -56,9 +56,12 @@ ValueEnumerator::ValueEnumerator(const Module *M) {
|
||||
|
||||
|
||||
// FIXME: std::partition the type and value tables so that first-class types
|
||||
// come earlier than aggregates.
|
||||
// come earlier than aggregates. FIXME: Emit a marker into the module
|
||||
// indicating which aggregates types AND values can be dropped form the table.
|
||||
|
||||
// FIXME: Sort type/value tables by frequency.
|
||||
|
||||
// FIXME: Sort constants by type to reduce size.
|
||||
}
|
||||
|
||||
/// EnumerateTypeSymbolTable - Insert all of the types in the specified symbol
|
||||
|
@ -35,15 +35,13 @@ public:
|
||||
// For each value, we remember its Value* and occurrence frequency.
|
||||
typedef std::vector<std::pair<const Value*, unsigned> > ValueList;
|
||||
private:
|
||||
TypeList Types;
|
||||
|
||||
typedef DenseMap<const Type*, unsigned> TypeMapType;
|
||||
TypeMapType TypeMap;
|
||||
TypeList Types;
|
||||
|
||||
ValueList Values;
|
||||
|
||||
typedef DenseMap<const Value*, unsigned> ValueMapType;
|
||||
ValueMapType ValueMap;
|
||||
ValueList Values;
|
||||
|
||||
|
||||
ValueEnumerator(const ValueEnumerator &); // DO NOT IMPLEMENT
|
||||
@ -63,7 +61,7 @@ public:
|
||||
return I->second-1;
|
||||
}
|
||||
|
||||
|
||||
const ValueList &getValues() const { return Values; }
|
||||
const TypeList &getTypes() const { return Types; }
|
||||
|
||||
/// incorporateFunction/purgeFunction - If you'd like to deal with a function,
|
||||
|
Loading…
Reference in New Issue
Block a user