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
/// 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.\r
+void linkCoreCLRGC();
+
/// Creates an ocaml-compatible garbage collector.
void linkOcamlGC();
(void) llvm::createGreedyRegisterAllocator();
(void) llvm::createDefaultPBQPRegisterAllocator();
+ llvm::linkCoreCLRGC();
llvm::linkOcamlGC();
llvm::linkErlangGC();
llvm::linkShadowStackGC();
CallingConvLower.cpp
CodeGen.cpp
CodeGenPrepare.cpp
+ CoreCLRGC.cpp
CriticalAntiDepBreaker.cpp
DFAPacketizer.cpp
DeadMachineInstructionElim.cpp
--- /dev/null
+//===-- CoreCLRGC.cpp - CoreCLR Runtime GC Strategy -----------------------===//\r
+//\r
+// The LLVM Compiler Infrastructure\r
+//\r
+// This file is distributed under the University of Illinois Open Source\r
+// License. See LICENSE.TXT for details.\r
+//\r
+//===----------------------------------------------------------------------===//\r
+//\r
+// This file contains a GCStrategy for the CoreCLR Runtime.\r
+// The strategy is similar to Statepoint-example GC, but differs from it in\r
+// certain aspects, such as:\r
+// 1) Base-pointers need not be explicitly tracked and reported for\r
+// interior pointers\r
+// 2) Uses a different format for encoding stack-maps\r
+// 3) Location of Safe-point polls: polls are only needed before loop-back edges\r
+// and before tail-calls (not needed at function-entry)\r
+//\r
+// The above differences in behavior are to be implemented in upcoming checkins.\r
+//\r
+//===----------------------------------------------------------------------===//\r
+\r
+#include "llvm/CodeGen/GCStrategy.h"\r
+#include "llvm/IR/DerivedTypes.h"\r
+#include "llvm/IR/Value.h"\r
+\r
+using namespace llvm;\r
+\r
+namespace {\r
+class CoreCLRGC : public GCStrategy {\r
+public:\r
+ CoreCLRGC() {\r
+ UseStatepoints = true;\r
+ // These options are all gc.root specific, we specify them so that the\r
+ // gc.root lowering code doesn't run.\r
+ InitRoots = false;\r
+ NeededSafePoints = 0;\r
+ UsesMetadata = false;\r
+ CustomRoots = false;\r
+ }\r
+ Optional<bool> isGCManagedPointer(const Value *V) const override {\r
+ // Method is only valid on pointer typed values.\r
+ PointerType *PT = cast<PointerType>(V->getType());\r
+ // We pick addrspace(1) as our GC managed heap. \r
+ return (1 == PT->getAddressSpace());\r
+ }\r
+};\r
+}\r
+\r
+static GCRegistry::Add<CoreCLRGC> X("coreclr",\r
+ "CoreCLR-compatible GC");\r
+\r
+namespace llvm {\r
+void linkCoreCLRGC() {}\r
+}\r
#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"
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();\r
+ const StringRef StatepointExampleName("statepoint-example");\r
+ const StringRef CoreCLRName("coreclr");\r
+ return (StatepointExampleName == FunctionGCName) ||\r
+ (CoreCLRName == FunctionGCName);
} else
return false;
}
#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"
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();\r
+ const StringRef StatepointExampleName("statepoint-example");\r
+ const StringRef CoreCLRName("coreclr");\r
+ return (StatepointExampleName == FunctionGCName) ||\r
+ (CoreCLRName == FunctionGCName);
+ }
+ else
return false;
}
--- /dev/null
+; RUN: opt %s -S -place-safepoints | FileCheck %s\r
+\r
+; Basic test to make sure that safepoints are placed\r
+; for CoreCLR GC\r
+\r
+declare void @foo()\r
+\r
+define void @test_simple_call() gc "coreclr" {\r
+; CHECK-LABEL: test_simple_call\r
+entry:\r
+ br label %other\r
+other:\r
+; CHECK-LABEL: other\r
+; CHECK: statepoint\r
+; CHECK-NOT: gc.result\r
+ call void @foo()\r
+ ret void\r
+}\r
+\r
+; This function is inlined when inserting a poll. To avoid recursive\r
+; issues, make sure we don't place safepoints in it.\r
+declare void @do_safepoint()\r
+define void @gc.safepoint_poll() {\r
+; CHECK-LABEL: gc.safepoint_poll\r
+; CHECK-LABEL: entry\r
+; CHECK-NEXT: do_safepoint\r
+; CHECK-NEXT: ret void\r
+entry:\r
+ call void @do_safepoint()\r
+ ret void\r
+}\r