Skip to content

Android splitstack implementation #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 41 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
68e3324
Create a gcregroot intrinsic and lower it in fastisel
pcwalton May 9, 2012
b228089
Temp commit
pcwalton May 9, 2012
d5997b8
Spiller hacks
pcwalton May 9, 2012
db31289
Trace GC roots back, implement asm printing
pcwalton May 10, 2012
2e6cc24
Read GC register roots in the GC metadata
pcwalton May 12, 2012
a0a4b7d
Translate llvm.gcroot intrinsics in the fast instruction selector
pcwalton May 14, 2012
32469c9
Implement a generic GC strategy and metadata printer
pcwalton May 15, 2012
e250845
Remove debug code from SplitKit
pcwalton May 15, 2012
79610c0
Root arguments too
pcwalton May 15, 2012
5a92253
Record callee-saved registers in the GC maps
pcwalton May 15, 2012
b95a226
Allow substructures to be rooted
pcwalton May 15, 2012
c571db9
Automatically insert calls to llvm.gcroot for all allocas that contai…
pcwalton May 16, 2012
7aca23c
Implement SSA-based liveness
pcwalton May 19, 2012
8c7a59d
Add live-out analysis; use strict domination instead of domination fo…
pcwalton May 19, 2012
03520e7
Don't root dead variables
pcwalton May 21, 2012
ccbe419
Only root original pointers, not any derived pointers
pcwalton May 22, 2012
6eab463
Handle GC register roots specially in the fast instruction selector t…
pcwalton May 22, 2012
bd00197
Fixed LiveIRVariables pass to detect back edges correctly.
Jun 23, 2012
f6d0021
Fix automatic rooting allocas of structs.
Jul 3, 2012
eb73ca4
Emit per-module list of safe points.
Jul 9, 2012
b004ec4
Update compiler-rt and clang.
graydon Jul 24, 2012
c9fc4ba
Minor rebase fallout.
graydon Jul 24, 2012
0422516
Better debugging support for the LiveIRVariables pass.
Jul 25, 2012
07c84ee
Remove unnecessary basic blocks on -O0 to avoid spending time in Live…
Jul 26, 2012
5551b39
Switch LiveIRVariables over to BitVector to avoid DenseMap overhead.
Jul 26, 2012
5be7786
Fix compiling llvm on ARM
erickt Jul 26, 2012
2ba0494
Rewrite LiveIRVariables with better algorithm.
Jul 30, 2012
e1667b6
Better debugging output for LiveIRVariables.
Jul 31, 2012
77a2e80
Fix LiveIRVariables for arguments to functions.
Jul 31, 2012
e2207b6
Fix LiveIRVariables for values returned from functions.
Aug 1, 2012
dd7c86d
Emit metadata pointers by addrspace.
Aug 13, 2012
8ab0094
Don't auto-root structs because they are root explicitly by the compi…
Aug 16, 2012
f16ed1c
Temporarily turn off automatic register roots until SelectionDAG works.
Aug 21, 2012
5e5064a
update clang to HEAD
erickt Sep 28, 2012
4fe715e
detects python3 on bleeding-edge systems
benbrittain Jul 17, 2012
326b1a2
Another llvm rebase, this time updating compiler-rt
erickt Sep 30, 2012
c51053b
Rollback to older compiler-rt to fix 10.6.8 issues
erickt Oct 1, 2012
dc4cdbf
Hack around llvm 14013
brson Oct 5, 2012
accc36b
GCStrategy: disable LiveIRVariables analysis.
graydon Nov 15, 2012
5d2eb5c
splitstack for arm
ILyoan Feb 22, 2013
060d258
Implemented argument stack size for TARGET::ARM
ILyoan Feb 28, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[submodule "projects/compiler-rt"]
path = projects/compiler-rt
url = git://github.com/brson/compiler-rt
[submodule "tools/clang"]
path = tools/clang
url = git://github.com/brson/clang
12 changes: 11 additions & 1 deletion Makefile.rules
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,16 @@ ifndef TARGET_NATIVE_ARCH
TARGET_NATIVE_ARCH := $(ARCH)
endif

PYTHONVERSION := $(shell expr `python -V 2>&1 | cut -f1 -d. | sed -e 's/Python //'`)

ifeq "$(PYTHONVERSION)" "3"
PYTHON := python2
endif

ifndef PYTHON
PYTHON := python
endif

# The rule to create the LLVMBuild Makefile fragment as well as the llvm-config
# library table.
#
Expand All @@ -97,7 +107,7 @@ endif
$(LLVMBuildMakeFrag): $(PROJ_SRC_ROOT)/Makefile.rules \
$(PROJ_OBJ_ROOT)/Makefile.config
$(Echo) Constructing LLVMBuild project information.
$(Verb) $(LLVMBuildTool) \
$(Verb) $(PYTHON) $(LLVMBuildTool) \
--native-target "$(TARGET_NATIVE_ARCH)" \
--enable-targets "$(TARGETS_TO_BUILD)" \
--enable-optional-components "$(OPTIONAL_COMPONENTS)" \
Expand Down
5 changes: 4 additions & 1 deletion include/llvm/CodeGen/FastISel.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class AllocaInst;
class Constant;
class ConstantFP;
class FunctionLoweringInfo;
class GCFunctionInfo;
class Instruction;
class LoadInst;
class MachineBasicBlock;
Expand Down Expand Up @@ -59,6 +60,7 @@ class FastISel {
const TargetLowering &TLI;
const TargetRegisterInfo &TRI;
const TargetLibraryInfo *LibInfo;
GCFunctionInfo &GFI;

/// The position of the last instruction for materializing constants
/// for use in the current block. It resets to EmitStartPt when it
Expand Down Expand Up @@ -147,7 +149,8 @@ class FastISel {

protected:
explicit FastISel(FunctionLoweringInfo &funcInfo,
const TargetLibraryInfo *libInfo);
const TargetLibraryInfo *libInfo,
GCFunctionInfo &gcInfo);

/// TargetSelectInstruction - This method is called by target-independent
/// code when the normal FastISel process fails to select an instruction.
Expand Down
228 changes: 207 additions & 21 deletions include/llvm/CodeGen/GCMetadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,20 @@
#define LLVM_CODEGEN_GCMETADATA_H

#include "llvm/Pass.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/DebugLoc.h"
#include <utility>

namespace llvm {
class AllocaInst;
class AsmPrinter;
class GCStrategy;
class Constant;
class MCSymbol;
class TargetData;
class Value;

namespace GC {
/// PointKind - The type of a collector-safe point.
Expand All @@ -66,25 +71,82 @@ namespace llvm {
: Kind(K), Label(L), Loc(DL) {}
};

/// GCRootLoc - The location of an object managed by the garbage collector.
union GCRootLoc {
int StackOffset; //< Offset from the stack pointer.
int PhysReg; //< A physical register.
};

/// GCRoot - Metadata for a pointer to an object managed by the garbage
/// collector.
struct GCRoot {
int Num; ///< Usually a frame index.
int StackOffset; ///< Offset from the stack pointer.
const Constant *Metadata; ///< Metadata straight from the call
///< to llvm.gcroot.
int Num; //< Positive integers indicate a frame index; -1
// indicates a register.
GCRootLoc Loc; //< The location of the object.
const Constant *Metadata;//< Metadata straight from the call to llvm.gcroot.

inline bool isStack() const { return Num >= 0; }
inline bool isReg() const { return !isStack(); }

GCRoot(int N, unsigned Offset, const Constant *MD)
: Num(N), Metadata(MD) {
Loc.StackOffset = Offset;
}
};

/// GCCalleeSavedInfo - Metadata for a callee-saved register.
struct GCCalleeSavedInfo {
unsigned Reg; //< The physical register.
int Num; //< The frame index.
int StackOffset; //< Offset from the stack pointer.

GCRoot(int N, const Constant *MD) : Num(N), StackOffset(-1), Metadata(MD) {}
GCCalleeSavedInfo(unsigned R, int N, int SO)
: Reg(R), Num(N), StackOffset(SO) {}
};


/// GCFunctionInfo - Garbage collection metadata for a single function.
///
class GCFunctionInfo {
public:
class live_iterator {
GCFunctionInfo &GCFI;
unsigned PointIndex;
unsigned RootIndex;

inline void advance() {
for (++RootIndex; RootIndex < GCFI.roots_size(); ++RootIndex) {
if (GCFI.isLive(PointIndex, RootIndex))
break;
}
}

public:
live_iterator(GCFunctionInfo &FI, unsigned PI, unsigned RI)
: GCFI(FI), PointIndex(PI), RootIndex(RI) {
if (RootIndex < GCFI.roots_size() &&
!GCFI.isLive(PointIndex, RootIndex)) {
advance();
}
}

inline live_iterator& operator++() { advance(); return *this; }

inline const GCRoot &operator*() { return GCFI.getRoot(RootIndex); }
inline const GCRoot *operator->() { return &operator*(); }

inline bool operator==(const live_iterator &Other) {
return &GCFI == &Other.GCFI && PointIndex == Other.PointIndex &&
RootIndex == Other.RootIndex;
}
inline bool operator!=(const live_iterator &Other) {
return !operator==(Other);
}
};

typedef std::vector<GCPoint>::iterator iterator;
typedef std::vector<GCRoot>::iterator roots_iterator;
typedef std::vector<GCRoot>::const_iterator live_iterator;
typedef std::vector<GCCalleeSavedInfo>::iterator callee_saved_iterator;

private:
const Function &F;
Expand All @@ -93,15 +155,20 @@ namespace llvm {
std::vector<GCRoot> Roots;
std::vector<GCPoint> SafePoints;

// FIXME: Liveness. A 2D BitVector, perhaps?
//
// BitVector Liveness;
//
// bool islive(int point, int root) =
// Liveness[point * SafePoints.size() + root]
//
// The bit vector is the more compact representation where >3.2% of roots
// are live per safe point (1.5% on 64-bit hosts).
BitVector Liveness;

// A bit vector that describes whether each root is global or local.
// Local roots have their liveness described by the Liveness bit vector,
// while global roots are live everywhere.
BitVector GlobalRoots;

// A mapping from safe point symbols to indices.
DenseMap<MCSymbol *, unsigned> SafePointSymbols;

// A list of callee-saved registers in this function.
std::vector<GCCalleeSavedInfo> CSInfo;

public:
GCFunctionInfo(const Function &F, GCStrategy &S);
Expand All @@ -115,25 +182,127 @@ namespace llvm {
///
GCStrategy &getStrategy() { return S; }

/// addStackRoot - Registers a root that lives on the stack. Num is the
/// stack object ID for the alloca (if the code generator is
// using MachineFrameInfo).
void addStackRoot(int Num, const Constant *Metadata) {
Roots.push_back(GCRoot(Num, Metadata));
/// addGlobalRoot - Registers a root that lives on the stack and is live
/// everywhere. Num is the stack object ID for the alloca (if the code
/// generator is using MachineFrameInfo), while Offset is the offset in
/// bytes from that stack object.
void addGlobalRoot(int Num, unsigned Offset, const Constant *Metadata) {
assert(Liveness.size() == 0 && "Can't add roots after finalization!");
unsigned RootIndex = Roots.size();
Roots.push_back(GCRoot(Num, Offset, Metadata));

GlobalRoots.resize(Roots.size(), false);
GlobalRoots[RootIndex] = true;
}

/// addRegRoot - Registers a root that lives in a register and returns its
/// index. The actual physical register will be filled in after register
/// allocation.
unsigned addRegRoot(const Constant *Metadata) {
assert(Liveness.size() == 0 && "Can't add roots after finalization!");
unsigned RootIndex = Roots.size();
Roots.push_back(GCRoot(-1, 0, Metadata));
return RootIndex;
}

/// addSafePoint - Notes the existence of a safe point. Num is the ID of the
/// label just prior to the safe point (if the code generator is using
/// MachineModuleInfo).
void addSafePoint(GC::PointKind Kind, MCSymbol *Label, DebugLoc DL) {
assert(Liveness.size() == 0 &&
"Can't add safe points after roots have been finalized!");
unsigned PointIndex = SafePoints.size();
SafePoints.push_back(GCPoint(Kind, Label, DL));
SafePointSymbols[Label] = PointIndex;
}

/// getPoint - Returns the safe point with the given index.
GCPoint &getPoint(unsigned PointIndex) {
assert(PointIndex < SafePoints.size() &&
"No point with that index exists!");
return SafePoints[PointIndex];
}

/// getPointIndex - Returns the index of the safe point with the given
/// label.
unsigned getPointIndex(MCSymbol *Label) {
assert(SafePointSymbols.find(Label) != SafePointSymbols.end() &&
"No safe point with that symbol exists!");
return SafePointSymbols[Label];
}

/// getRoot - Returns the root with the given index.
inline GCRoot &getRoot(unsigned RootIndex) {
assert(RootIndex < Roots.size() && "Invalid root index!");
return Roots[RootIndex];
}

/// finalizeRoots - Creates the liveness bit vector. After this call, no
/// more roots or safe points can be added.
void finalizeRoots() {
Liveness.resize(Roots.size() * SafePoints.size(), false);
GlobalRoots.resize(Roots.size(), false);
}

/// isRootGlobal - Returns true if the given root is a global root or false
/// otherwise.
bool isRootGlobal(unsigned RootIndex) const {
return GlobalRoots[RootIndex];
}

/// isLive - Returns true if the given root is live at the supplied safe
/// point or false otherwise.
bool isLive(unsigned PointIndex, unsigned RootIndex) const {
assert(Liveness.size() != 0 &&
"Liveness is not available until roots have been finalized!");
assert(RootIndex < Roots.size() && "Invalid root index!");
assert(PointIndex < SafePoints.size() && "Invalid safe point index!");
return GlobalRoots[RootIndex] ||
Liveness[PointIndex * Roots.size() + RootIndex];
}

/// setLive - Adjusts the liveness of the given root at the supplied safe
/// point.
void setLive(unsigned PointIndex, unsigned RootIndex, bool Live) {
assert(Liveness.size() != 0 &&
"Liveness is not available until roots have been finalized!");
assert(!GlobalRoots[RootIndex] &&
"Cannot adjust the liveness of a global root!");
assert(RootIndex < Roots.size() && "Invalid root index!");
assert(PointIndex < SafePoints.size() && "Invalid safe point index!");
Liveness[PointIndex * Roots.size() + RootIndex] = Live;
}

/// spillRegRoot - Moves the given register root to the stack and assigns
/// it the supplied frame index.
void spillRegRoot(unsigned RootIndex, int FrameIndex) {
assert(RootIndex < Roots.size() && "Invalid root index!");
assert(FrameIndex >= 0 && "Invalid frame index!");
Roots[RootIndex].Num = FrameIndex;
}

/// setRootLoc - Sets the final location of the given register root.
inline void setRootLoc(unsigned RootIndex, GCRootLoc Loc) {
assert(RootIndex < Roots.size() && "Invalid root index!");
Roots[RootIndex].Loc = Loc;
}

/// findGCRootOrigin - Traces the argument to llvm.gcroot back to its
/// origin (through any pointer casts or GEPs) and returns the original
/// value as well as the byte offset of the pointer of interest within it.
static std::pair<const AllocaInst *, unsigned>
findGCRootOrigin(const TargetData *TD, const Value *V);

/// getFrameSize/setFrameSize - Records the function's frame size.
///
uint64_t getFrameSize() const { return FrameSize; }
void setFrameSize(uint64_t S) { FrameSize = S; }

/// addCalleeSavedReg - Records information about a callee-saved register.
void addCalleeSavedReg(unsigned Reg, int FI, int SO) {
CSInfo.push_back(GCCalleeSavedInfo(Reg, FI, SO));
}

/// begin/end - Iterators for safe points.
///
iterator begin() { return SafePoints.begin(); }
Expand All @@ -148,9 +317,26 @@ namespace llvm {

/// live_begin/live_end - Iterators for live roots at a given safe point.
///
live_iterator live_begin(const iterator &p) { return roots_begin(); }
live_iterator live_end (const iterator &p) { return roots_end(); }
size_t live_size(const iterator &p) const { return roots_size(); }
live_iterator live_begin(unsigned PointIndex) {
return live_iterator(*this, PointIndex, 0);
}
live_iterator live_end(unsigned PointIndex) {
return live_iterator(*this, PointIndex, roots_size());
}
size_t live_size(unsigned PointIndex) {
size_t Count = 0;
for (unsigned RI = 0; RI < Roots.size(); ++RI) {
if (isLive(PointIndex, RI))
++Count;
}
return Count;
}

/// callee_saved_begin/callee_saved_end - Iterators for callee-saved
/// registers.
callee_saved_iterator callee_saved_begin() { return CSInfo.begin(); }
callee_saved_iterator callee_saved_end() { return CSInfo.end(); }
size_t callee_saved_size() { return CSInfo.size(); }
};


Expand Down
10 changes: 9 additions & 1 deletion include/llvm/CodeGen/GCStrategy.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,12 @@ namespace llvm {
bool CustomWriteBarriers; ///< Default is to insert stores.
bool CustomRoots; ///< Default is to pass through to backend.
bool CustomSafePoints; ///< Default is to use NeededSafePoints
///< to find safe points.
/// to find safe points.
bool InitRoots; ///< If set, roots are nulled during lowering.
bool UsesMetadata; ///< If set, backend must emit metadata tables.
bool UsesAutomaticRoots; ///< If set, calls to llvm.gcroot are inserted
/// automatically for pointers in address space
/// 1.

public:
GCStrategy();
Expand Down Expand Up @@ -128,6 +131,11 @@ namespace llvm {
/// usesMetadata - If set, appropriate metadata tables must be emitted by
/// the back-end (assembler, JIT, or otherwise).
bool usesMetadata() const { return UsesMetadata; }

/// usesAutomaticRoots - If set, calls to llvm.gcroot are automatically
/// inserted for structs that contain pointers in
/// address space 1.
bool usesAutomaticRoots() const { return UsesAutomaticRoots; }

/// begin/end - Iterators for function metadata.
///
Expand Down
6 changes: 6 additions & 0 deletions include/llvm/CodeGen/GCs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ namespace llvm {
/// Creates a shadow stack garbage collector. This collector requires no code
/// generator support.
void linkShadowStackGC();

/// Creates a generic garbage collector.
void linkGenericGC();

/// Creates a generic metadata printer.
void linkGenericGCPrinter();
}

#endif
Loading