1*9880d681SAndroid Build Coastguard Worker //===-- GCRootLowering.cpp - Garbage collection infrastructure ------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker //
10*9880d681SAndroid Build Coastguard Worker // This file implements the lowering for the gc.root mechanism.
11*9880d681SAndroid Build Coastguard Worker //
12*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
13*9880d681SAndroid Build Coastguard Worker
14*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/GCMetadata.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/GCStrategy.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFrameInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineFunctionPass.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineInstrBuilder.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/MachineModuleInfo.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/CodeGen/Passes.h"
21*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Dominators.h"
22*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/IntrinsicInst.h"
23*9880d681SAndroid Build Coastguard Worker #include "llvm/IR/Module.h"
24*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/Debug.h"
25*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
26*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
27*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetFrameLowering.h"
28*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetInstrInfo.h"
29*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetMachine.h"
30*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetRegisterInfo.h"
31*9880d681SAndroid Build Coastguard Worker #include "llvm/Target/TargetSubtargetInfo.h"
32*9880d681SAndroid Build Coastguard Worker
33*9880d681SAndroid Build Coastguard Worker using namespace llvm;
34*9880d681SAndroid Build Coastguard Worker
35*9880d681SAndroid Build Coastguard Worker namespace {
36*9880d681SAndroid Build Coastguard Worker
37*9880d681SAndroid Build Coastguard Worker /// LowerIntrinsics - This pass rewrites calls to the llvm.gcread or
38*9880d681SAndroid Build Coastguard Worker /// llvm.gcwrite intrinsics, replacing them with simple loads and stores as
39*9880d681SAndroid Build Coastguard Worker /// directed by the GCStrategy. It also performs automatic root initialization
40*9880d681SAndroid Build Coastguard Worker /// and custom intrinsic lowering.
41*9880d681SAndroid Build Coastguard Worker class LowerIntrinsics : public FunctionPass {
42*9880d681SAndroid Build Coastguard Worker bool PerformDefaultLowering(Function &F, GCStrategy &Coll);
43*9880d681SAndroid Build Coastguard Worker
44*9880d681SAndroid Build Coastguard Worker public:
45*9880d681SAndroid Build Coastguard Worker static char ID;
46*9880d681SAndroid Build Coastguard Worker
47*9880d681SAndroid Build Coastguard Worker LowerIntrinsics();
48*9880d681SAndroid Build Coastguard Worker const char *getPassName() const override;
49*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override;
50*9880d681SAndroid Build Coastguard Worker
51*9880d681SAndroid Build Coastguard Worker bool doInitialization(Module &M) override;
52*9880d681SAndroid Build Coastguard Worker bool runOnFunction(Function &F) override;
53*9880d681SAndroid Build Coastguard Worker };
54*9880d681SAndroid Build Coastguard Worker
55*9880d681SAndroid Build Coastguard Worker /// GCMachineCodeAnalysis - This is a target-independent pass over the machine
56*9880d681SAndroid Build Coastguard Worker /// function representation to identify safe points for the garbage collector
57*9880d681SAndroid Build Coastguard Worker /// in the machine code. It inserts labels at safe points and populates a
58*9880d681SAndroid Build Coastguard Worker /// GCMetadata record for each function.
59*9880d681SAndroid Build Coastguard Worker class GCMachineCodeAnalysis : public MachineFunctionPass {
60*9880d681SAndroid Build Coastguard Worker GCFunctionInfo *FI;
61*9880d681SAndroid Build Coastguard Worker MachineModuleInfo *MMI;
62*9880d681SAndroid Build Coastguard Worker const TargetInstrInfo *TII;
63*9880d681SAndroid Build Coastguard Worker
64*9880d681SAndroid Build Coastguard Worker void FindSafePoints(MachineFunction &MF);
65*9880d681SAndroid Build Coastguard Worker void VisitCallPoint(MachineBasicBlock::iterator MI);
66*9880d681SAndroid Build Coastguard Worker MCSymbol *InsertLabel(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
67*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL) const;
68*9880d681SAndroid Build Coastguard Worker
69*9880d681SAndroid Build Coastguard Worker void FindStackOffsets(MachineFunction &MF);
70*9880d681SAndroid Build Coastguard Worker
71*9880d681SAndroid Build Coastguard Worker public:
72*9880d681SAndroid Build Coastguard Worker static char ID;
73*9880d681SAndroid Build Coastguard Worker
74*9880d681SAndroid Build Coastguard Worker GCMachineCodeAnalysis();
75*9880d681SAndroid Build Coastguard Worker void getAnalysisUsage(AnalysisUsage &AU) const override;
76*9880d681SAndroid Build Coastguard Worker
77*9880d681SAndroid Build Coastguard Worker bool runOnMachineFunction(MachineFunction &MF) override;
78*9880d681SAndroid Build Coastguard Worker };
79*9880d681SAndroid Build Coastguard Worker }
80*9880d681SAndroid Build Coastguard Worker
81*9880d681SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
82*9880d681SAndroid Build Coastguard Worker
83*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_BEGIN(LowerIntrinsics, "gc-lowering", "GC Lowering", false,
84*9880d681SAndroid Build Coastguard Worker false)
INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)85*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_DEPENDENCY(GCModuleInfo)
86*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS_END(LowerIntrinsics, "gc-lowering", "GC Lowering", false, false)
87*9880d681SAndroid Build Coastguard Worker
88*9880d681SAndroid Build Coastguard Worker FunctionPass *llvm::createGCLoweringPass() { return new LowerIntrinsics(); }
89*9880d681SAndroid Build Coastguard Worker
90*9880d681SAndroid Build Coastguard Worker char LowerIntrinsics::ID = 0;
91*9880d681SAndroid Build Coastguard Worker
LowerIntrinsics()92*9880d681SAndroid Build Coastguard Worker LowerIntrinsics::LowerIntrinsics() : FunctionPass(ID) {
93*9880d681SAndroid Build Coastguard Worker initializeLowerIntrinsicsPass(*PassRegistry::getPassRegistry());
94*9880d681SAndroid Build Coastguard Worker }
95*9880d681SAndroid Build Coastguard Worker
getPassName() const96*9880d681SAndroid Build Coastguard Worker const char *LowerIntrinsics::getPassName() const {
97*9880d681SAndroid Build Coastguard Worker return "Lower Garbage Collection Instructions";
98*9880d681SAndroid Build Coastguard Worker }
99*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const100*9880d681SAndroid Build Coastguard Worker void LowerIntrinsics::getAnalysisUsage(AnalysisUsage &AU) const {
101*9880d681SAndroid Build Coastguard Worker FunctionPass::getAnalysisUsage(AU);
102*9880d681SAndroid Build Coastguard Worker AU.addRequired<GCModuleInfo>();
103*9880d681SAndroid Build Coastguard Worker AU.addPreserved<DominatorTreeWrapperPass>();
104*9880d681SAndroid Build Coastguard Worker }
105*9880d681SAndroid Build Coastguard Worker
NeedsDefaultLoweringPass(const GCStrategy & C)106*9880d681SAndroid Build Coastguard Worker static bool NeedsDefaultLoweringPass(const GCStrategy &C) {
107*9880d681SAndroid Build Coastguard Worker // Default lowering is necessary only if read or write barriers have a default
108*9880d681SAndroid Build Coastguard Worker // action. The default for roots is no action.
109*9880d681SAndroid Build Coastguard Worker return !C.customWriteBarrier() || !C.customReadBarrier() ||
110*9880d681SAndroid Build Coastguard Worker C.initializeRoots();
111*9880d681SAndroid Build Coastguard Worker }
112*9880d681SAndroid Build Coastguard Worker
113*9880d681SAndroid Build Coastguard Worker /// doInitialization - If this module uses the GC intrinsics, find them now.
doInitialization(Module & M)114*9880d681SAndroid Build Coastguard Worker bool LowerIntrinsics::doInitialization(Module &M) {
115*9880d681SAndroid Build Coastguard Worker GCModuleInfo *MI = getAnalysisIfAvailable<GCModuleInfo>();
116*9880d681SAndroid Build Coastguard Worker assert(MI && "LowerIntrinsics didn't require GCModuleInfo!?");
117*9880d681SAndroid Build Coastguard Worker for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
118*9880d681SAndroid Build Coastguard Worker if (!I->isDeclaration() && I->hasGC())
119*9880d681SAndroid Build Coastguard Worker MI->getFunctionInfo(*I); // Instantiate the GC strategy.
120*9880d681SAndroid Build Coastguard Worker
121*9880d681SAndroid Build Coastguard Worker return false;
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker
124*9880d681SAndroid Build Coastguard Worker /// CouldBecomeSafePoint - Predicate to conservatively determine whether the
125*9880d681SAndroid Build Coastguard Worker /// instruction could introduce a safe point.
CouldBecomeSafePoint(Instruction * I)126*9880d681SAndroid Build Coastguard Worker static bool CouldBecomeSafePoint(Instruction *I) {
127*9880d681SAndroid Build Coastguard Worker // The natural definition of instructions which could introduce safe points
128*9880d681SAndroid Build Coastguard Worker // are:
129*9880d681SAndroid Build Coastguard Worker //
130*9880d681SAndroid Build Coastguard Worker // - call, invoke (AfterCall, BeforeCall)
131*9880d681SAndroid Build Coastguard Worker // - phis (Loops)
132*9880d681SAndroid Build Coastguard Worker // - invoke, ret, unwind (Exit)
133*9880d681SAndroid Build Coastguard Worker //
134*9880d681SAndroid Build Coastguard Worker // However, instructions as seemingly inoccuous as arithmetic can become
135*9880d681SAndroid Build Coastguard Worker // libcalls upon lowering (e.g., div i64 on a 32-bit platform), so instead
136*9880d681SAndroid Build Coastguard Worker // it is necessary to take a conservative approach.
137*9880d681SAndroid Build Coastguard Worker
138*9880d681SAndroid Build Coastguard Worker if (isa<AllocaInst>(I) || isa<GetElementPtrInst>(I) || isa<StoreInst>(I) ||
139*9880d681SAndroid Build Coastguard Worker isa<LoadInst>(I))
140*9880d681SAndroid Build Coastguard Worker return false;
141*9880d681SAndroid Build Coastguard Worker
142*9880d681SAndroid Build Coastguard Worker // llvm.gcroot is safe because it doesn't do anything at runtime.
143*9880d681SAndroid Build Coastguard Worker if (CallInst *CI = dyn_cast<CallInst>(I))
144*9880d681SAndroid Build Coastguard Worker if (Function *F = CI->getCalledFunction())
145*9880d681SAndroid Build Coastguard Worker if (Intrinsic::ID IID = F->getIntrinsicID())
146*9880d681SAndroid Build Coastguard Worker if (IID == Intrinsic::gcroot)
147*9880d681SAndroid Build Coastguard Worker return false;
148*9880d681SAndroid Build Coastguard Worker
149*9880d681SAndroid Build Coastguard Worker return true;
150*9880d681SAndroid Build Coastguard Worker }
151*9880d681SAndroid Build Coastguard Worker
InsertRootInitializers(Function & F,AllocaInst ** Roots,unsigned Count)152*9880d681SAndroid Build Coastguard Worker static bool InsertRootInitializers(Function &F, AllocaInst **Roots,
153*9880d681SAndroid Build Coastguard Worker unsigned Count) {
154*9880d681SAndroid Build Coastguard Worker // Scroll past alloca instructions.
155*9880d681SAndroid Build Coastguard Worker BasicBlock::iterator IP = F.getEntryBlock().begin();
156*9880d681SAndroid Build Coastguard Worker while (isa<AllocaInst>(IP))
157*9880d681SAndroid Build Coastguard Worker ++IP;
158*9880d681SAndroid Build Coastguard Worker
159*9880d681SAndroid Build Coastguard Worker // Search for initializers in the initial BB.
160*9880d681SAndroid Build Coastguard Worker SmallPtrSet<AllocaInst *, 16> InitedRoots;
161*9880d681SAndroid Build Coastguard Worker for (; !CouldBecomeSafePoint(&*IP); ++IP)
162*9880d681SAndroid Build Coastguard Worker if (StoreInst *SI = dyn_cast<StoreInst>(IP))
163*9880d681SAndroid Build Coastguard Worker if (AllocaInst *AI =
164*9880d681SAndroid Build Coastguard Worker dyn_cast<AllocaInst>(SI->getOperand(1)->stripPointerCasts()))
165*9880d681SAndroid Build Coastguard Worker InitedRoots.insert(AI);
166*9880d681SAndroid Build Coastguard Worker
167*9880d681SAndroid Build Coastguard Worker // Add root initializers.
168*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
169*9880d681SAndroid Build Coastguard Worker
170*9880d681SAndroid Build Coastguard Worker for (AllocaInst **I = Roots, **E = Roots + Count; I != E; ++I)
171*9880d681SAndroid Build Coastguard Worker if (!InitedRoots.count(*I)) {
172*9880d681SAndroid Build Coastguard Worker StoreInst *SI = new StoreInst(
173*9880d681SAndroid Build Coastguard Worker ConstantPointerNull::get(cast<PointerType>((*I)->getAllocatedType())),
174*9880d681SAndroid Build Coastguard Worker *I);
175*9880d681SAndroid Build Coastguard Worker SI->insertAfter(*I);
176*9880d681SAndroid Build Coastguard Worker MadeChange = true;
177*9880d681SAndroid Build Coastguard Worker }
178*9880d681SAndroid Build Coastguard Worker
179*9880d681SAndroid Build Coastguard Worker return MadeChange;
180*9880d681SAndroid Build Coastguard Worker }
181*9880d681SAndroid Build Coastguard Worker
182*9880d681SAndroid Build Coastguard Worker /// runOnFunction - Replace gcread/gcwrite intrinsics with loads and stores.
183*9880d681SAndroid Build Coastguard Worker /// Leave gcroot intrinsics; the code generator needs to see those.
runOnFunction(Function & F)184*9880d681SAndroid Build Coastguard Worker bool LowerIntrinsics::runOnFunction(Function &F) {
185*9880d681SAndroid Build Coastguard Worker // Quick exit for functions that do not use GC.
186*9880d681SAndroid Build Coastguard Worker if (!F.hasGC())
187*9880d681SAndroid Build Coastguard Worker return false;
188*9880d681SAndroid Build Coastguard Worker
189*9880d681SAndroid Build Coastguard Worker GCFunctionInfo &FI = getAnalysis<GCModuleInfo>().getFunctionInfo(F);
190*9880d681SAndroid Build Coastguard Worker GCStrategy &S = FI.getStrategy();
191*9880d681SAndroid Build Coastguard Worker
192*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
193*9880d681SAndroid Build Coastguard Worker
194*9880d681SAndroid Build Coastguard Worker if (NeedsDefaultLoweringPass(S))
195*9880d681SAndroid Build Coastguard Worker MadeChange |= PerformDefaultLowering(F, S);
196*9880d681SAndroid Build Coastguard Worker
197*9880d681SAndroid Build Coastguard Worker return MadeChange;
198*9880d681SAndroid Build Coastguard Worker }
199*9880d681SAndroid Build Coastguard Worker
PerformDefaultLowering(Function & F,GCStrategy & S)200*9880d681SAndroid Build Coastguard Worker bool LowerIntrinsics::PerformDefaultLowering(Function &F, GCStrategy &S) {
201*9880d681SAndroid Build Coastguard Worker bool LowerWr = !S.customWriteBarrier();
202*9880d681SAndroid Build Coastguard Worker bool LowerRd = !S.customReadBarrier();
203*9880d681SAndroid Build Coastguard Worker bool InitRoots = S.initializeRoots();
204*9880d681SAndroid Build Coastguard Worker
205*9880d681SAndroid Build Coastguard Worker SmallVector<AllocaInst *, 32> Roots;
206*9880d681SAndroid Build Coastguard Worker
207*9880d681SAndroid Build Coastguard Worker bool MadeChange = false;
208*9880d681SAndroid Build Coastguard Worker for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
209*9880d681SAndroid Build Coastguard Worker for (BasicBlock::iterator II = BB->begin(), E = BB->end(); II != E;) {
210*9880d681SAndroid Build Coastguard Worker if (IntrinsicInst *CI = dyn_cast<IntrinsicInst>(II++)) {
211*9880d681SAndroid Build Coastguard Worker Function *F = CI->getCalledFunction();
212*9880d681SAndroid Build Coastguard Worker switch (F->getIntrinsicID()) {
213*9880d681SAndroid Build Coastguard Worker case Intrinsic::gcwrite:
214*9880d681SAndroid Build Coastguard Worker if (LowerWr) {
215*9880d681SAndroid Build Coastguard Worker // Replace a write barrier with a simple store.
216*9880d681SAndroid Build Coastguard Worker Value *St =
217*9880d681SAndroid Build Coastguard Worker new StoreInst(CI->getArgOperand(0), CI->getArgOperand(2), CI);
218*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(St);
219*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
220*9880d681SAndroid Build Coastguard Worker }
221*9880d681SAndroid Build Coastguard Worker break;
222*9880d681SAndroid Build Coastguard Worker case Intrinsic::gcread:
223*9880d681SAndroid Build Coastguard Worker if (LowerRd) {
224*9880d681SAndroid Build Coastguard Worker // Replace a read barrier with a simple load.
225*9880d681SAndroid Build Coastguard Worker Value *Ld = new LoadInst(CI->getArgOperand(1), "", CI);
226*9880d681SAndroid Build Coastguard Worker Ld->takeName(CI);
227*9880d681SAndroid Build Coastguard Worker CI->replaceAllUsesWith(Ld);
228*9880d681SAndroid Build Coastguard Worker CI->eraseFromParent();
229*9880d681SAndroid Build Coastguard Worker }
230*9880d681SAndroid Build Coastguard Worker break;
231*9880d681SAndroid Build Coastguard Worker case Intrinsic::gcroot:
232*9880d681SAndroid Build Coastguard Worker if (InitRoots) {
233*9880d681SAndroid Build Coastguard Worker // Initialize the GC root, but do not delete the intrinsic. The
234*9880d681SAndroid Build Coastguard Worker // backend needs the intrinsic to flag the stack slot.
235*9880d681SAndroid Build Coastguard Worker Roots.push_back(
236*9880d681SAndroid Build Coastguard Worker cast<AllocaInst>(CI->getArgOperand(0)->stripPointerCasts()));
237*9880d681SAndroid Build Coastguard Worker }
238*9880d681SAndroid Build Coastguard Worker break;
239*9880d681SAndroid Build Coastguard Worker default:
240*9880d681SAndroid Build Coastguard Worker continue;
241*9880d681SAndroid Build Coastguard Worker }
242*9880d681SAndroid Build Coastguard Worker
243*9880d681SAndroid Build Coastguard Worker MadeChange = true;
244*9880d681SAndroid Build Coastguard Worker }
245*9880d681SAndroid Build Coastguard Worker }
246*9880d681SAndroid Build Coastguard Worker }
247*9880d681SAndroid Build Coastguard Worker
248*9880d681SAndroid Build Coastguard Worker if (Roots.size())
249*9880d681SAndroid Build Coastguard Worker MadeChange |= InsertRootInitializers(F, Roots.begin(), Roots.size());
250*9880d681SAndroid Build Coastguard Worker
251*9880d681SAndroid Build Coastguard Worker return MadeChange;
252*9880d681SAndroid Build Coastguard Worker }
253*9880d681SAndroid Build Coastguard Worker
254*9880d681SAndroid Build Coastguard Worker // -----------------------------------------------------------------------------
255*9880d681SAndroid Build Coastguard Worker
256*9880d681SAndroid Build Coastguard Worker char GCMachineCodeAnalysis::ID = 0;
257*9880d681SAndroid Build Coastguard Worker char &llvm::GCMachineCodeAnalysisID = GCMachineCodeAnalysis::ID;
258*9880d681SAndroid Build Coastguard Worker
259*9880d681SAndroid Build Coastguard Worker INITIALIZE_PASS(GCMachineCodeAnalysis, "gc-analysis",
260*9880d681SAndroid Build Coastguard Worker "Analyze Machine Code For Garbage Collection", false, false)
261*9880d681SAndroid Build Coastguard Worker
GCMachineCodeAnalysis()262*9880d681SAndroid Build Coastguard Worker GCMachineCodeAnalysis::GCMachineCodeAnalysis() : MachineFunctionPass(ID) {}
263*9880d681SAndroid Build Coastguard Worker
getAnalysisUsage(AnalysisUsage & AU) const264*9880d681SAndroid Build Coastguard Worker void GCMachineCodeAnalysis::getAnalysisUsage(AnalysisUsage &AU) const {
265*9880d681SAndroid Build Coastguard Worker MachineFunctionPass::getAnalysisUsage(AU);
266*9880d681SAndroid Build Coastguard Worker AU.setPreservesAll();
267*9880d681SAndroid Build Coastguard Worker AU.addRequired<MachineModuleInfo>();
268*9880d681SAndroid Build Coastguard Worker AU.addRequired<GCModuleInfo>();
269*9880d681SAndroid Build Coastguard Worker }
270*9880d681SAndroid Build Coastguard Worker
InsertLabel(MachineBasicBlock & MBB,MachineBasicBlock::iterator MI,const DebugLoc & DL) const271*9880d681SAndroid Build Coastguard Worker MCSymbol *GCMachineCodeAnalysis::InsertLabel(MachineBasicBlock &MBB,
272*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator MI,
273*9880d681SAndroid Build Coastguard Worker const DebugLoc &DL) const {
274*9880d681SAndroid Build Coastguard Worker MCSymbol *Label = MBB.getParent()->getContext().createTempSymbol();
275*9880d681SAndroid Build Coastguard Worker BuildMI(MBB, MI, DL, TII->get(TargetOpcode::GC_LABEL)).addSym(Label);
276*9880d681SAndroid Build Coastguard Worker return Label;
277*9880d681SAndroid Build Coastguard Worker }
278*9880d681SAndroid Build Coastguard Worker
VisitCallPoint(MachineBasicBlock::iterator CI)279*9880d681SAndroid Build Coastguard Worker void GCMachineCodeAnalysis::VisitCallPoint(MachineBasicBlock::iterator CI) {
280*9880d681SAndroid Build Coastguard Worker // Find the return address (next instruction), too, so as to bracket the call
281*9880d681SAndroid Build Coastguard Worker // instruction.
282*9880d681SAndroid Build Coastguard Worker MachineBasicBlock::iterator RAI = CI;
283*9880d681SAndroid Build Coastguard Worker ++RAI;
284*9880d681SAndroid Build Coastguard Worker
285*9880d681SAndroid Build Coastguard Worker if (FI->getStrategy().needsSafePoint(GC::PreCall)) {
286*9880d681SAndroid Build Coastguard Worker MCSymbol *Label = InsertLabel(*CI->getParent(), CI, CI->getDebugLoc());
287*9880d681SAndroid Build Coastguard Worker FI->addSafePoint(GC::PreCall, Label, CI->getDebugLoc());
288*9880d681SAndroid Build Coastguard Worker }
289*9880d681SAndroid Build Coastguard Worker
290*9880d681SAndroid Build Coastguard Worker if (FI->getStrategy().needsSafePoint(GC::PostCall)) {
291*9880d681SAndroid Build Coastguard Worker MCSymbol *Label = InsertLabel(*CI->getParent(), RAI, CI->getDebugLoc());
292*9880d681SAndroid Build Coastguard Worker FI->addSafePoint(GC::PostCall, Label, CI->getDebugLoc());
293*9880d681SAndroid Build Coastguard Worker }
294*9880d681SAndroid Build Coastguard Worker }
295*9880d681SAndroid Build Coastguard Worker
FindSafePoints(MachineFunction & MF)296*9880d681SAndroid Build Coastguard Worker void GCMachineCodeAnalysis::FindSafePoints(MachineFunction &MF) {
297*9880d681SAndroid Build Coastguard Worker for (MachineFunction::iterator BBI = MF.begin(), BBE = MF.end(); BBI != BBE;
298*9880d681SAndroid Build Coastguard Worker ++BBI)
299*9880d681SAndroid Build Coastguard Worker for (MachineBasicBlock::iterator MI = BBI->begin(), ME = BBI->end();
300*9880d681SAndroid Build Coastguard Worker MI != ME; ++MI)
301*9880d681SAndroid Build Coastguard Worker if (MI->isCall()) {
302*9880d681SAndroid Build Coastguard Worker // Do not treat tail or sibling call sites as safe points. This is
303*9880d681SAndroid Build Coastguard Worker // legal since any arguments passed to the callee which live in the
304*9880d681SAndroid Build Coastguard Worker // remnants of the callers frame will be owned and updated by the
305*9880d681SAndroid Build Coastguard Worker // callee if required.
306*9880d681SAndroid Build Coastguard Worker if (MI->isTerminator())
307*9880d681SAndroid Build Coastguard Worker continue;
308*9880d681SAndroid Build Coastguard Worker VisitCallPoint(MI);
309*9880d681SAndroid Build Coastguard Worker }
310*9880d681SAndroid Build Coastguard Worker }
311*9880d681SAndroid Build Coastguard Worker
FindStackOffsets(MachineFunction & MF)312*9880d681SAndroid Build Coastguard Worker void GCMachineCodeAnalysis::FindStackOffsets(MachineFunction &MF) {
313*9880d681SAndroid Build Coastguard Worker const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering();
314*9880d681SAndroid Build Coastguard Worker assert(TFI && "TargetRegisterInfo not available!");
315*9880d681SAndroid Build Coastguard Worker
316*9880d681SAndroid Build Coastguard Worker for (GCFunctionInfo::roots_iterator RI = FI->roots_begin();
317*9880d681SAndroid Build Coastguard Worker RI != FI->roots_end();) {
318*9880d681SAndroid Build Coastguard Worker // If the root references a dead object, no need to keep it.
319*9880d681SAndroid Build Coastguard Worker if (MF.getFrameInfo()->isDeadObjectIndex(RI->Num)) {
320*9880d681SAndroid Build Coastguard Worker RI = FI->removeStackRoot(RI);
321*9880d681SAndroid Build Coastguard Worker } else {
322*9880d681SAndroid Build Coastguard Worker unsigned FrameReg; // FIXME: surely GCRoot ought to store the
323*9880d681SAndroid Build Coastguard Worker // register that the offset is from?
324*9880d681SAndroid Build Coastguard Worker RI->StackOffset = TFI->getFrameIndexReference(MF, RI->Num, FrameReg);
325*9880d681SAndroid Build Coastguard Worker ++RI;
326*9880d681SAndroid Build Coastguard Worker }
327*9880d681SAndroid Build Coastguard Worker }
328*9880d681SAndroid Build Coastguard Worker }
329*9880d681SAndroid Build Coastguard Worker
runOnMachineFunction(MachineFunction & MF)330*9880d681SAndroid Build Coastguard Worker bool GCMachineCodeAnalysis::runOnMachineFunction(MachineFunction &MF) {
331*9880d681SAndroid Build Coastguard Worker // Quick exit for functions that do not use GC.
332*9880d681SAndroid Build Coastguard Worker if (!MF.getFunction()->hasGC())
333*9880d681SAndroid Build Coastguard Worker return false;
334*9880d681SAndroid Build Coastguard Worker
335*9880d681SAndroid Build Coastguard Worker FI = &getAnalysis<GCModuleInfo>().getFunctionInfo(*MF.getFunction());
336*9880d681SAndroid Build Coastguard Worker MMI = &getAnalysis<MachineModuleInfo>();
337*9880d681SAndroid Build Coastguard Worker TII = MF.getSubtarget().getInstrInfo();
338*9880d681SAndroid Build Coastguard Worker
339*9880d681SAndroid Build Coastguard Worker // Find the size of the stack frame. There may be no correct static frame
340*9880d681SAndroid Build Coastguard Worker // size, we use UINT64_MAX to represent this.
341*9880d681SAndroid Build Coastguard Worker const MachineFrameInfo *MFI = MF.getFrameInfo();
342*9880d681SAndroid Build Coastguard Worker const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
343*9880d681SAndroid Build Coastguard Worker const bool DynamicFrameSize = MFI->hasVarSizedObjects() ||
344*9880d681SAndroid Build Coastguard Worker RegInfo->needsStackRealignment(MF);
345*9880d681SAndroid Build Coastguard Worker FI->setFrameSize(DynamicFrameSize ? UINT64_MAX : MFI->getStackSize());
346*9880d681SAndroid Build Coastguard Worker
347*9880d681SAndroid Build Coastguard Worker // Find all safe points.
348*9880d681SAndroid Build Coastguard Worker if (FI->getStrategy().needsSafePoints())
349*9880d681SAndroid Build Coastguard Worker FindSafePoints(MF);
350*9880d681SAndroid Build Coastguard Worker
351*9880d681SAndroid Build Coastguard Worker // Find the concrete stack offsets for all roots (stack slots)
352*9880d681SAndroid Build Coastguard Worker FindStackOffsets(MF);
353*9880d681SAndroid Build Coastguard Worker
354*9880d681SAndroid Build Coastguard Worker return false;
355*9880d681SAndroid Build Coastguard Worker }
356