//===-- SlotCalculator.cpp - Calculate what slots values land in ----------===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This file implements a useful analysis step to figure out what numbered slots
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
+#include "llvm/InlineAsm.h"
#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/SymbolTable.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
#include <functional>
-
using namespace llvm;
#if 0
// Add all of the global variables to the value table...
//
- for (Module::const_giterator I = TheModule->gbegin(), E = TheModule->gend();
- I != E; ++I)
+ for (Module::const_global_iterator I = TheModule->global_begin(),
+ E = TheModule->global_end(); I != E; ++I)
getOrCreateSlot(I);
// Scavenge the types out of the functions, then add the functions themselves
// Add all of the module level constants used as initializers
//
- for (Module::const_giterator I = TheModule->gbegin(), E = TheModule->gend();
- I != E; ++I)
+ for (Module::const_global_iterator I = TheModule->global_begin(),
+ E = TheModule->global_end(); I != E; ++I)
if (I->hasInitializer())
getOrCreateSlot(I->getInitializer());
TypePlane &Plane = Table[plane];
unsigned FirstNonStringID = 0;
for (unsigned i = 0, e = Plane.size(); i != e; ++i)
- if (isa<ConstantAggregateZero>(Plane[i]) ||
- isa<UndefValue>(Plane[i]) ||
- cast<ConstantArray>(Plane[i])->isString()) {
+ if (isa<ConstantAggregateZero>(Plane[i]) ||
+ (isa<ConstantArray>(Plane[i]) &&
+ cast<ConstantArray>(Plane[i])->isString())) {
// Check to see if we have to shuffle this string around. If not,
// don't do anything.
if (i != FirstNonStringID) {
// Swap the plane entries....
std::swap(Plane[i], Plane[FirstNonStringID]);
-
+
// Keep the NodeMap up to date.
NodeMap[Plane[i]] = i;
NodeMap[Plane[FirstNonStringID]] = FirstNonStringID;
}
}
}
-
- // Scan all of the functions for their constants, which allows us to emit
- // more compact modules. This is optional, and is just used to compactify
+
+ // Scan all of the functions for their constants, which allows us to emit
+ // more compact modules. This is optional, and is just used to compactify
// the constants used by different functions together.
//
- // This functionality tends to produce smaller bytecode files. This should
- // not be used in the future by clients that want to, for example, build and
- // emit functions on the fly. For now, however, it is unconditionally
+ // This functionality tends to produce smaller bytecode files. This should
+ // not be used in the future by clients that want to, for example, build and
+ // emit functions on the fly. For now, however, it is unconditionally
// enabled.
ModuleContainsAllFunctionConstants = true;
SC_DEBUG("Inserting function constants:\n");
for (Module::const_iterator F = TheModule->begin(), E = TheModule->end();
F != E; ++F) {
- for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I){
- for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (isa<Constant>(I->getOperand(op)) &&
- !isa<GlobalValue>(I->getOperand(op)))
- getOrCreateSlot(I->getOperand(op));
+ for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
+ for (User::const_op_iterator OI = I->op_begin(), E = I->op_end();
+ OI != E; ++OI) {
+ if ((isa<Constant>(*OI) && !isa<GlobalValue>(*OI)) ||
+ isa<InlineAsm>(*OI))
+ getOrCreateSlot(*OI);
+ }
getOrCreateSlot(I->getType());
- if (const VANextInst *VAN = dyn_cast<VANextInst>(&*I))
- getOrCreateSlot(VAN->getArgType());
}
processSymbolTableConstants(&F->getSymbolTable());
}
getOrCreateSlot(TI->second);
// Now do the values.
- for (SymbolTable::plane_const_iterator PI = ST->plane_begin(),
+ for (SymbolTable::plane_const_iterator PI = ST->plane_begin(),
PE = ST->plane_end(); PI != PE; ++PI)
for (SymbolTable::value_const_iterator VI = PI->second.begin(),
VE = PI->second.end(); VI != VE; ++VI)
getOrCreateSlot(TI->second);
// Now do the constant values in all planes
- for (SymbolTable::plane_const_iterator PI = ST->plane_begin(),
+ for (SymbolTable::plane_const_iterator PI = ST->plane_begin(),
PE = ST->plane_end(); PI != PE; ++PI)
for (SymbolTable::value_const_iterator VI = PI->second.begin(),
VE = PI->second.end(); VI != VE; ++VI)
SC_DEBUG("begin processFunction!\n");
// If we emitted all of the function constants, build a compaction table.
- if ( ModuleContainsAllFunctionConstants)
+ if (ModuleContainsAllFunctionConstants)
buildCompactionTable(F);
// Update the ModuleLevel entries to be accurate.
ModuleTypeLevel = Types.size();
// Iterate over function arguments, adding them to the value table...
- for(Function::const_aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
+ for(Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); I != E; ++I)
getOrCreateSlot(I);
- if ( !ModuleContainsAllFunctionConstants ) {
+ if (!ModuleContainsAllFunctionConstants) {
// Iterate over all of the instructions in the function, looking for
// constant values that are referenced. Add these to the value pools
// before any nonconstant values. This will be turned into the constant
// pool for the bytecode writer.
//
-
+
// Emit all of the constants that are being used by the instructions in
// the function...
- constant_iterator CI = constant_begin(F);
- constant_iterator CE = constant_end(F);
- while ( CI != CE ) {
- this->getOrCreateSlot(*CI);
- ++CI;
- }
-
+ for (constant_iterator CI = constant_begin(F), CE = constant_end(F);
+ CI != CE; ++CI)
+ getOrCreateSlot(*CI);
+
// If there is a symbol table, it is possible that the user has names for
// constants that are not being used. In this case, we will have problems
- // if we don't emit the constants now, because otherwise we will get
+ // if we don't emit the constants now, because otherwise we will get
// symbol table references to constants not in the output. Scan for these
// constants now.
//
getOrCreateSlot(BB);
for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I!=E; ++I) {
getOrCreateSlot(I);
- if (const VANextInst *VAN = dyn_cast<VANextInst>(I))
- getOrCreateSlot(VAN->getArgType());
}
}
NodeMap.erase(Plane.back()); // Erase from nodemap
Plane.pop_back(); // Shrink plane
}
-
+
Table.pop_back(); // Nuke the plane, we don't like it.
}
}
SC_DEBUG("end purgeFunction!\n");
}
-static inline bool hasNullValue(unsigned TyID) {
- return TyID != Type::LabelTyID && TyID != Type::VoidTyID;
+static inline bool hasNullValue(const Type *Ty) {
+ return Ty != Type::LabelTy && Ty != Type::VoidTy && !isa<OpaqueType>(Ty);
}
/// getOrCreateCompactionTableSlot - This method is used to build up the initial
// Make sure to insert the null entry if the thing we are inserting is not a
// null constant.
- if (TyPlane.empty() && hasNullValue(V->getType()->getTypeID())) {
+ if (TyPlane.empty() && hasNullValue(V->getType())) {
Value *ZeroInitializer = Constant::getNullValue(V->getType());
if (V != ZeroInitializer) {
TyPlane.push_back(ZeroInitializer);
}
// Next, include any types used by function arguments.
- for (Function::const_aiterator I = F->abegin(), E = F->aend(); I != E; ++I)
+ for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
+ I != E; ++I)
getOrCreateCompactionTableSlot(I->getType());
// Next, find all of the types and values that are referred to by the
for (const_inst_iterator I = inst_begin(F), E = inst_end(F); I != E; ++I) {
getOrCreateCompactionTableSlot(I->getType());
for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (isa<Constant>(I->getOperand(op)))
+ if (isa<Constant>(I->getOperand(op)) || isa<InlineAsm>(I->getOperand(op)))
getOrCreateCompactionTableSlot(I->getOperand(op));
- if (const VANextInst *VAN = dyn_cast<VANextInst>(&*I))
- getOrCreateCompactionTableSlot(VAN->getArgType());
}
// Do the types in the symbol table
getOrCreateCompactionTableSlot(TI->second);
// Now do the constants and global values
- for (SymbolTable::plane_const_iterator PI = ST.plane_begin(),
+ for (SymbolTable::plane_const_iterator PI = ST.plane_begin(),
PE = ST.plane_end(); PI != PE; ++PI)
for (SymbolTable::value_const_iterator VI = PI->second.begin(),
VE = PI->second.end(); VI != VE; ++VI)
assert(Ty->getTypeID() != Type::LabelTyID);
getOrCreateCompactionTableSlot(Constant::getNullValue(Ty));
}
-
+
// Okay, now at this point, we have a legal compaction table. Since we want
// to emit the smallest possible binaries, do not compactify the type plane if
// it will not save us anything. Because we have not yet incorporated the
// function body itself yet, we don't know whether or not it's a good idea to
// compactify other planes. We will defer this decision until later.
TypeList &GlobalTypes = Types;
-
+
// All of the values types will be scrunched to the start of the types plane
// of the global table. Figure out just how many there are.
assert(!GlobalTypes.empty() && "No global types???");
std::swap(CompactionTable, TmpCompactionTable);
TypeList TmpTypes;
std::swap(TmpTypes, CompactionTypes);
-
+
// Move each plane back over to the uncompactified plane
while (!TmpTypes.empty()) {
const Type *Ty = TmpTypes.back();
// Find the global slot number for this type.
int TySlot = getSlot(Ty);
assert(TySlot != -1 && "Type doesn't exist in global table?");
-
+
// Now we know where to put the compaction table plane.
if (CompactionTable.size() <= unsigned(TySlot))
CompactionTable.resize(TySlot+1);
if (GlobalSlot >= Table.size())
Table.resize(GlobalSlot+1);
TypePlane &GPlane = Table[GlobalSlot];
-
+
unsigned ModLevel = getModuleLevel(ctp);
unsigned NumFunctionObjs = CPlane.size()-ModLevel;
}
/// Determine if the compaction table is actually empty. Because the
-/// compaction table always includes the primitive type planes, we
+/// compaction table always includes the primitive type planes, we
/// can't just check getCompactionTable().size() because it will never
/// be zero. Furthermore, the ModuleLevel factors into whether a given
/// plane is empty or not. This function does the necessary computation
// If the module level is non-zero then at least the
// first element of the plane is valid and therefore not empty.
unsigned End = getModuleLevel(i);
- if (End != 0)
+ if (End != 0)
return false;
}
}
int SlotNo = getSlot(V); // Check to see if it's already in!
if (SlotNo != -1) return SlotNo;
+ if (const GlobalValue *GV = dyn_cast<GlobalValue>(V))
+ assert(GV->getParent() != 0 && "Global not embedded into a module!");
+
if (!isa<GlobalValue>(V)) // Initializers for globals are handled explicitly
if (const Constant *C = dyn_cast<Constant>(V)) {
assert(CompactionNodeMap.empty() &&
"All needed constants should be in the compaction map already!");
- // Do not index the characters that make up constant strings. We emit
- // constant strings as special entities that don't require their
+ // Do not index the characters that make up constant strings. We emit
+ // constant strings as special entities that don't require their
// individual characters to be emitted.
if (!isa<ConstantArray>(C) || !cast<ConstantArray>(C)->isString()) {
// This makes sure that if a constant has uses (for example an array of
return getOrCreateCompactionTableSlot(D);
}
- // If this node does not contribute to a plane, or if the node has a
+ // If this node does not contribute to a plane, or if the node has a
// name and we don't want names, then ignore the silly node... Note that types
// do need slot numbers so that we can keep track of where other values land.
//
} else {
Ty = Typ->getTypeID();
}
-
+
if (Table.size() <= Ty) // Make sure we have the type plane allocated...
Table.resize(Ty+1, TypePlane());
// If this is the first value to get inserted into the type plane, make sure
// to insert the implicit null value...
- if (Table[Ty].empty() && hasNullValue(Ty)) {
+ if (Table[Ty].empty() && hasNullValue(Typ)) {
Value *ZeroInitializer = Constant::getNullValue(Typ);
// If we are pushing zeroinit, it will be handled below.
unsigned DestSlot = NodeMap[D] = Table[Ty].size();
Table[Ty].push_back(D);
- SC_DEBUG(" Inserting value [" << Ty << "] = " << D << " slot=" <<
+ SC_DEBUG(" Inserting value [" << Ty << "] = " << D << " slot=" <<
DestSlot << " [");
// G = Global, C = Constant, T = Type, F = Function, o = other
- SC_DEBUG((isa<GlobalVariable>(D) ? "G" : (isa<Constant>(D) ? "C" :
+ SC_DEBUG((isa<GlobalVariable>(D) ? "G" : (isa<Constant>(D) ? "C" :
(isa<Function>(D) ? "F" : "o"))));
SC_DEBUG("]\n");
return (int)DestSlot;
return (int)DestSlot;
}
-// vim: sw=2 ai