-/// addSizeOfGlobal - add the size of the global (plus any alignment padding)
-/// into the running total Size.
-
-unsigned JITEmitter::addSizeOfGlobal(const GlobalVariable *GV, unsigned Size) {
- const Type *ElTy = GV->getType()->getElementType();
- size_t GVSize = (size_t)TheJIT->getTargetData()->getTypeAllocSize(ElTy);
- size_t GVAlign =
- (size_t)TheJIT->getTargetData()->getPreferredAlignment(GV);
- DEBUG(dbgs() << "JIT: Adding in size " << GVSize << " alignment " << GVAlign);
- DEBUG(GV->dump());
- // Assume code section ends with worst possible alignment, so first
- // variable needs maximal padding.
- if (Size==0)
- Size = 1;
- Size = ((Size+GVAlign-1)/GVAlign)*GVAlign;
- Size += GVSize;
- return Size;
-}
-
-/// addSizeOfGlobalsInConstantVal - find any globals that we haven't seen yet
-/// but are referenced from the constant; put them in SeenGlobals and the
-/// Worklist, and add their size into the running total Size.
-
-unsigned JITEmitter::addSizeOfGlobalsInConstantVal(
- const Constant *C,
- unsigned Size,
- SmallPtrSet<const GlobalVariable*, 8> &SeenGlobals,
- SmallVectorImpl<const GlobalVariable*> &Worklist) {
- // If its undefined, return the garbage.
- if (isa<UndefValue>(C))
- return Size;
-
- // If the value is a ConstantExpr
- if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(C)) {
- Constant *Op0 = CE->getOperand(0);
- switch (CE->getOpcode()) {
- case Instruction::GetElementPtr:
- case Instruction::Trunc:
- case Instruction::ZExt:
- case Instruction::SExt:
- case Instruction::FPTrunc:
- case Instruction::FPExt:
- case Instruction::UIToFP:
- case Instruction::SIToFP:
- case Instruction::FPToUI:
- case Instruction::FPToSI:
- case Instruction::PtrToInt:
- case Instruction::IntToPtr:
- case Instruction::BitCast: {
- Size = addSizeOfGlobalsInConstantVal(Op0, Size, SeenGlobals, Worklist);
- break;
- }
- case Instruction::Add:
- case Instruction::FAdd:
- case Instruction::Sub:
- case Instruction::FSub:
- case Instruction::Mul:
- case Instruction::FMul:
- case Instruction::UDiv:
- case Instruction::SDiv:
- case Instruction::URem:
- case Instruction::SRem:
- case Instruction::And:
- case Instruction::Or:
- case Instruction::Xor: {
- Size = addSizeOfGlobalsInConstantVal(Op0, Size, SeenGlobals, Worklist);
- Size = addSizeOfGlobalsInConstantVal(CE->getOperand(1), Size,
- SeenGlobals, Worklist);
- break;
- }
- default: {
- std::string msg;
- raw_string_ostream Msg(msg);
- Msg << "ConstantExpr not handled: " << *CE;
- report_fatal_error(Msg.str());
- }
- }
- }
-
- if (C->getType()->getTypeID() == Type::PointerTyID)
- if (const GlobalVariable* GV = dyn_cast<GlobalVariable>(C))
- if (SeenGlobals.insert(GV)) {
- Worklist.push_back(GV);
- Size = addSizeOfGlobal(GV, Size);
- }
-
- return Size;
-}
-
-/// addSizeOfGLobalsInInitializer - handle any globals that we haven't seen yet
-/// but are referenced from the given initializer.
-
-unsigned JITEmitter::addSizeOfGlobalsInInitializer(
- const Constant *Init,
- unsigned Size,
- SmallPtrSet<const GlobalVariable*, 8> &SeenGlobals,
- SmallVectorImpl<const GlobalVariable*> &Worklist) {
- if (!isa<UndefValue>(Init) &&
- !isa<ConstantVector>(Init) &&
- !isa<ConstantAggregateZero>(Init) &&
- !isa<ConstantArray>(Init) &&
- !isa<ConstantStruct>(Init) &&
- Init->getType()->isFirstClassType())
- Size = addSizeOfGlobalsInConstantVal(Init, Size, SeenGlobals, Worklist);
- return Size;
-}
-
-/// GetSizeOfGlobalsInBytes - walk the code for the function, looking for
-/// globals; then walk the initializers of those globals looking for more.
-/// If their size has not been considered yet, add it into the running total
-/// Size.
-
-unsigned JITEmitter::GetSizeOfGlobalsInBytes(MachineFunction &MF) {
- unsigned Size = 0;
- SmallPtrSet<const GlobalVariable*, 8> SeenGlobals;
-
- for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
- MBB != E; ++MBB) {
- for (MachineBasicBlock::const_iterator I = MBB->begin(), E = MBB->end();
- I != E; ++I) {
- const TargetInstrDesc &Desc = I->getDesc();
- const MachineInstr &MI = *I;
- unsigned NumOps = Desc.getNumOperands();
- for (unsigned CurOp = 0; CurOp < NumOps; CurOp++) {
- const MachineOperand &MO = MI.getOperand(CurOp);
- if (MO.isGlobal()) {
- const GlobalValue* V = MO.getGlobal();
- const GlobalVariable *GV = dyn_cast<const GlobalVariable>(V);
- if (!GV)
- continue;
- // If seen in previous function, it will have an entry here.
- if (TheJIT->getPointerToGlobalIfAvailable(
- const_cast<GlobalVariable *>(GV)))
- continue;
- // If seen earlier in this function, it will have an entry here.
- // FIXME: it should be possible to combine these tables, by
- // assuming the addresses of the new globals in this module
- // start at 0 (or something) and adjusting them after codegen
- // complete. Another possibility is to grab a marker bit in GV.
- if (SeenGlobals.insert(GV))
- // A variable as yet unseen. Add in its size.
- Size = addSizeOfGlobal(GV, Size);
- }
- }
- }
- }
- DEBUG(dbgs() << "JIT: About to look through initializers\n");
- // Look for more globals that are referenced only from initializers.
- SmallVector<const GlobalVariable*, 8> Worklist(
- SeenGlobals.begin(), SeenGlobals.end());
- while (!Worklist.empty()) {
- const GlobalVariable* GV = Worklist.back();
- Worklist.pop_back();
- if (GV->hasInitializer())
- Size = addSizeOfGlobalsInInitializer(GV->getInitializer(), Size,
- SeenGlobals, Worklist);
- }
-
- return Size;
-}
-