Add a GCStrategy for CoreCLR

This change adds a new GC strategy for supporting the CoreCLR runtime.

This strategy is currently identical to Statepoint-example GC, 
but is necessary for several upcoming changes specific to CoreCLR, such as:

1. Base-pointers not explicitly reported for interior pointers
2. Different format for stack-map encoding
3. Location of Safe-point polls: polls are only needed before loop-back edges and before tail-calls (not needed at function-entry)
4. Runtime specific handshake between calls to managed/unmanaged functions.



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237753 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Swaroop Sridhar 2015-05-20 01:07:23 +00:00
parent a6f501cb97
commit 95d08bce87
7 changed files with 105 additions and 5 deletions

View File

@ -21,6 +21,9 @@ class GCMetadataPrinter;
/// FIXME: Collector instances are not useful on their own. These no longer
/// serve any purpose except to link in the plugins.
/// Creates a CoreCLR-compatible garbage collector.
void linkCoreCLRGC();
/// Creates an ocaml-compatible garbage collector.
void linkOcamlGC();

View File

@ -36,6 +36,7 @@ namespace {
(void) llvm::createGreedyRegisterAllocator();
(void) llvm::createDefaultPBQPRegisterAllocator();
llvm::linkCoreCLRGC();
llvm::linkOcamlGC();
llvm::linkErlangGC();
llvm::linkShadowStackGC();

View File

@ -9,6 +9,7 @@ add_llvm_library(LLVMCodeGen
CallingConvLower.cpp
CodeGen.cpp
CodeGenPrepare.cpp
CoreCLRGC.cpp
CriticalAntiDepBreaker.cpp
DFAPacketizer.cpp
DeadMachineInstructionElim.cpp

55
lib/CodeGen/CoreCLRGC.cpp Normal file
View File

@ -0,0 +1,55 @@
//===-- CoreCLRGC.cpp - CoreCLR Runtime GC Strategy -----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a GCStrategy for the CoreCLR Runtime.
// The strategy is similar to Statepoint-example GC, but differs from it in
// certain aspects, such as:
// 1) Base-pointers need not be explicitly tracked and reported for
// interior pointers
// 2) Uses a different format for encoding stack-maps
// 3) Location of Safe-point polls: polls are only needed before loop-back edges
// and before tail-calls (not needed at function-entry)
//
// The above differences in behavior are to be implemented in upcoming checkins.
//
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/GCStrategy.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Value.h"
using namespace llvm;
namespace {
class CoreCLRGC : public GCStrategy {
public:
CoreCLRGC() {
UseStatepoints = true;
// These options are all gc.root specific, we specify them so that the
// gc.root lowering code doesn't run.
InitRoots = false;
NeededSafePoints = 0;
UsesMetadata = false;
CustomRoots = false;
}
Optional<bool> isGCManagedPointer(const Value *V) const override {
// Method is only valid on pointer typed values.
PointerType *PT = cast<PointerType>(V->getType());
// We pick addrspace(1) as our GC managed heap.
return (1 == PT->getAddressSpace());
}
};
}
static GCRegistry::Add<CoreCLRGC> X("coreclr",
"CoreCLR-compatible GC");
namespace llvm {
void linkCoreCLRGC() {}
}

View File

@ -53,6 +53,7 @@
#include "llvm/ADT/SetOperations.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/Analysis/ScalarEvolution.h"
@ -523,8 +524,11 @@ static bool isGCSafepointPoll(Function &F) {
static bool shouldRewriteFunction(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
const std::string StatepointExampleName("statepoint-example");
return StatepointExampleName == F.getGC();
const char *FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||
(CoreCLRName == FunctionGCName);
} else
return false;
}

View File

@ -19,6 +19,7 @@
#include "llvm/ADT/Statistic.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Dominators.h"
@ -2201,9 +2202,13 @@ static bool insertParsePoints(Function &F, DominatorTree &DT, Pass *P,
static bool shouldRewriteStatepointsIn(Function &F) {
// TODO: This should check the GCStrategy
if (F.hasGC()) {
const std::string StatepointExampleName("statepoint-example");
return StatepointExampleName == F.getGC();
} else
const char *FunctionGCName = F.getGC();
const StringRef StatepointExampleName("statepoint-example");
const StringRef CoreCLRName("coreclr");
return (StatepointExampleName == FunctionGCName) ||
(CoreCLRName == FunctionGCName);
}
else
return false;
}

View File

@ -0,0 +1,31 @@
; RUN: opt %s -S -place-safepoints | FileCheck %s
; Basic test to make sure that safepoints are placed
; for CoreCLR GC
declare void @foo()
define void @test_simple_call() gc "coreclr" {
; CHECK-LABEL: test_simple_call
entry:
br label %other
other:
; CHECK-LABEL: other
; CHECK: statepoint
; CHECK-NOT: gc.result
call void @foo()
ret void
}
; This function is inlined when inserting a poll. To avoid recursive
; issues, make sure we don't place safepoints in it.
declare void @do_safepoint()
define void @gc.safepoint_poll() {
; CHECK-LABEL: gc.safepoint_poll
; CHECK-LABEL: entry
; CHECK-NEXT: do_safepoint
; CHECK-NEXT: ret void
entry:
call void @do_safepoint()
ret void
}