//
//===----------------------------------------------------------------------===//
+#include "llvm/CodeGen/GCMetadata.h"
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
/// directed by the GCStrategy. It also performs automatic root initialization
/// and custom intrinsic lowering.
class LowerIntrinsics : public FunctionPass {
- static bool NeedsDefaultLoweringPass(const GCStrategy &C);
- static bool NeedsCustomLoweringPass(const GCStrategy &C);
- static bool CouldBecomeSafePoint(Instruction *I);
bool PerformDefaultLowering(Function &F, GCStrategy &Coll);
- static bool InsertRootInitializers(Function &F, AllocaInst **Roots,
- unsigned Count);
public:
static char ID;
/// in the machine code. It inserts labels at safe points and populates a
/// GCMetadata record for each function.
class GCMachineCodeAnalysis : public MachineFunctionPass {
- const TargetMachine *TM;
GCFunctionInfo *FI;
MachineModuleInfo *MMI;
const TargetInstrInfo *TII;
AU.addPreserved<DominatorTreeWrapperPass>();
}
+static bool NeedsDefaultLoweringPass(const GCStrategy &C) {
+ // Default lowering is necessary only if read or write barriers have a default
+ // action. The default for roots is no action.
+ return !C.customWriteBarrier() || !C.customReadBarrier() ||
+ C.initializeRoots();
+}
+
/// doInitialization - If this module uses the GC intrinsics, find them now.
bool LowerIntrinsics::doInitialization(Module &M) {
- // FIXME: This is rather antisocial in the context of a JIT since it performs
- // work against the entire module. But this cannot be done at
- // runFunction time (initializeCustomLowering likely needs to change
- // the module).
GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
if (!I->isDeclaration() && I->hasGC())
MI->getFunctionInfo(*I); // Instantiate the GC strategy.
- bool MadeChange = false;
- for (GCModuleInfo::iterator I = MI->begin(), E = MI->end(); I != E; ++I)
- if (NeedsCustomLoweringPass(**I))
- if ((*I)->initializeCustomLowering(M))
- MadeChange = true;
+ return false;
+}
- return MadeChange;
+/// CouldBecomeSafePoint - Predicate to conservatively determine whether the
+/// instruction could introduce a safe point.
+static bool CouldBecomeSafePoint(Instruction *I) {
+ // The natural definition of instructions which could introduce safe points
+ // are:
+ //
+ // - call, invoke (AfterCall, BeforeCall)
+ // - phis (Loops)
+ // - invoke, ret, unwind (Exit)
+ //
+ // However, instructions as seemingly inoccuous as arithmetic can become
+ // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
+ // it is necessary to take a conservative approach.
+
+ if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
+ isa<LoadInst>(I))
+ return false;
+
+ // llvm.gcroot is safe because it doesn't do anything at runtime.
+ if (CallInst *CI = dyn_cast<CallInst>(I))
+ if (Function *F = CI->getCalledFunction())
+ if (Intrinsic::ID IID = F->getIntrinsicID())
+ if (IID == Intrinsic::gcroot)
+ return false;
+
+ return true;
}
-bool LowerIntrinsics::InsertRootInitializers(Function &F, AllocaInst **Roots,
- unsigned Count) {
+static bool InsertRootInitializers(Function &F, AllocaInst **Roots,
+ unsigned Count) {
// Scroll past alloca instructions.
BasicBlock::iterator IP = F.getEntryBlock().begin();
while (isa<AllocaInst>(IP))
return MadeChange;
}
-bool LowerIntrinsics::NeedsDefaultLoweringPass(const GCStrategy &C) {
- // Default lowering is necessary only if read or write barriers have a default
- // action. The default for roots is no action.
- return !C.customWriteBarrier() || !C.customReadBarrier() ||
- C.initializeRoots();
-}
-
-bool LowerIntrinsics::NeedsCustomLoweringPass(const GCStrategy &C) {
- // Custom lowering is only necessary if enabled for some action.
- return C.customWriteBarrier() || C.customReadBarrier() || C.customRoots();
-}
-
-/// CouldBecomeSafePoint - Predicate to conservatively determine whether the
-/// instruction could introduce a safe point.
-bool LowerIntrinsics::CouldBecomeSafePoint(Instruction *I) {
- // The natural definition of instructions which could introduce safe points
- // are:
- //
- // - call, invoke (AfterCall, BeforeCall)
- // - phis (Loops)
- // - invoke, ret, unwind (Exit)
- //
- // However, instructions as seemingly inoccuous as arithmetic can become
- // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
- // it is necessary to take a conservative approach.
-
- if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
- isa<LoadInst>(I))
- return false;
-
- // llvm.gcroot is safe because it doesn't do anything at runtime.
- if (CallInst *CI = dyn_cast<CallInst>(I))
- if (Function *F = CI->getCalledFunction())
- if (unsigned IID = F->getIntrinsicID())
- if (IID == Intrinsic::gcroot)
- return false;
-
- return true;
-}
-
/// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
/// Leave gcroot intrinsics; the code generator needs to see those.
bool LowerIntrinsics::runOnFunction(Function &F) {
if (NeedsDefaultLoweringPass(S))
MadeChange |= PerformDefaultLowering(F, S);
- bool UseCustomLoweringPass = NeedsCustomLoweringPass(S);
- if (UseCustomLoweringPass)
- MadeChange |= S.performCustomLowering(F);
-
- // Custom lowering may modify the CFG, so dominators must be recomputed.
- if (UseCustomLoweringPass) {
- if (DominatorTreeWrapperPass *DTWP =
- getAnalysisIfAvailable<DominatorTreeWrapperPass>())
- DTWP->getDomTree().recalculate(F);
- }
-
return MadeChange;
}
MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
DebugLoc DL) const {
- MCSymbol *Label = MBB.getParent()->getContext().CreateTempSymbol();
+ MCSymbol *Label = MBB.getParent()->getContext().createTempSymbol();
BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
return Label;
}
++BBI)
for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end();
MI != ME; ++MI)
- if (MI->isCall())
+ if (MI->isCall()) {
+ // Do not treat tail or sibling call sites as safe points. This is
+ // legal since any arguments passed to the callee which live in the
+ // remnants of the callers frame will be owned and updated by the
+ // callee if required.
+ if (MI->isTerminator())
+ continue;
VisitCallPoint(MI);
+ }
}
void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
- const TargetFrameLowering *TFI = TM->getSubtargetImpl()->getFrameLowering();
+ const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
assert(TFI && "TargetRegisterInfo not available!");
for (GCFunctionInfo::roots_iterator RI = FI->roots_begin();
if (MF.getFrameInfo()->isDeadObjectIndex(RI->Num)) {
RI = FI->removeStackRoot(RI);
} else {
- RI->StackOffset = TFI->getFrameIndexOffset(MF, RI->Num);
+ unsigned FrameReg; // FIXME: surely GCRoot ought to store the
+ // register that the offset is from?
+ RI->StackOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg);
++RI;
}
}
return false;
FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction());
- if (!FI->getStrategy().needsSafePoints())
- return false;
-
- TM = &MF.getTarget();
MMI = &getAnalysis<MachineModuleInfo>();
- TII = TM->getSubtargetImpl()->getInstrInfo();
+ TII = MF.getSubtarget().getInstrInfo();
- // Find the size of the stack frame.
- FI->setFrameSize(MF.getFrameInfo()->getStackSize());
+ // Find the size of the stack frame. There may be no correct static frame
+ // size, we use UINT64_MAX to represent this.
+ const MachineFrameInfo *MFI = MF.getFrameInfo();
+ const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
+ const bool DynamicFrameSize = MFI->hasVarSizedObjects() ||
+ RegInfo->needsStackRealignment(MF);
+ FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI->getStackSize());
// Find all safe points.
- if (FI->getStrategy().customSafePoints()) {
- FI->getStrategy().findCustomSafePoints(*FI, MF);
- } else {
+ if (FI->getStrategy().needsSafePoints())
FindSafePoints(MF);
- }
- // Find the stack offsets for all roots.
+ // Find the concrete stack offsets for all roots (stack slots)
FindStackOffsets(MF);
return false;