aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/MemoryHandler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/MemoryHandler.cc')
-rw-r--r--lib/CodeGen/MemoryHandler.cc159
1 files changed, 0 insertions, 159 deletions
diff --git a/lib/CodeGen/MemoryHandler.cc b/lib/CodeGen/MemoryHandler.cc
deleted file mode 100644
index 7cb62b3..0000000
--- a/lib/CodeGen/MemoryHandler.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-#include "cps/MemoryHandler.h"
-#include "cps/ExceptionHandler.h"
-#include "cps/RuntimeCheck.h"
-#include "cps/TypeSystem.h"
-#include <climits>
-#include <cstddef>
-
-using namespace llvm;
-using namespace cps;
-
-Function *MemoryHandler::createHelper(const char *Name, ArrayRef<Type *> Args) {
- auto *F = Function::Create(FunctionType::get(PointerType::getUnqual(Context), Args, false),
- Function::InternalLinkage, Name, Module);
- Exceptions.prepareFunction(F);
- Builder.SetInsertPoint(BasicBlock::Create(Context, "entry", F));
- return F;
-}
-
-void MemoryHandler::ensureRuntime() {
- if (AllocateFn) return;
- IRBuilderBase::InsertPointGuard Guard(Builder);
- auto *Ptr = PointerType::getUnqual(Context);
- auto *I32 = Type::getInt32Ty(Context);
- SizeTy = Type::getIntNTy(Context, sizeof(std::size_t) * CHAR_BIT);
- NodeTy = StructType::create(Context, {Ptr, Ptr}, "__cps_memory_node");
- Head = new GlobalVariable(Module, Ptr, false, GlobalValue::InternalLinkage,
- ConstantPointerNull::get(Ptr), "__cps_memory_head");
- Malloc = Module.getOrInsertFunction("malloc", FunctionType::get(Ptr, {SizeTy}, false));
- Free = Module.getOrInsertFunction("free", FunctionType::get(Type::getVoidTy(Context), {Ptr}, false));
- Realloc = Module.getOrInsertFunction("realloc", FunctionType::get(Ptr, {Ptr, SizeTy}, false));
- AllocationError = Builder.CreateGlobalString("[Fatal] line %d: Memory allocation failed\n",
- "err_allocation", 0, &Module);
- TrackingError = Builder.CreateGlobalString("[Fatal] line %d: Allocation tracking failed\n",
- "err_tracking", 0, &Module);
- InvalidAddress = Builder.CreateGlobalString("[Fatal] line %d: Invalid memory address (not an active allocation)\n",
- "err_memory_address", 0, &Module);
- FindFn = createHelper("__cps_memory_find", {Ptr, I32});
- buildFind();
- AllocateFn = createHelper("__cps_memory_allocate", {SizeTy, I32});
- buildAllocate();
- ReleaseFn = createHelper("__cps_memory_release", {Ptr, I32});
- buildRelease();
- ResizeFn = createHelper("__cps_memory_resize", {Ptr, SizeTy, I32});
- buildResize();
-}
-
-// Return the address of the list link that owns the matching node. This also
-// lets release unlink the head or an interior node through the same operation.
-void MemoryHandler::buildFind() {
- auto *Ptr = PointerType::getUnqual(Context);
- Value *Address = FindFn->getArg(0), *Line = FindFn->getArg(1);
- auto *Entry = Builder.GetInsertBlock();
- auto *Loop = BasicBlock::Create(Context, "search", FindFn);
- auto *Found = BasicBlock::Create(Context, "found", FindFn);
- Builder.CreateBr(Loop);
- Builder.SetInsertPoint(Loop);
- auto *Link = Builder.CreatePHI(Ptr, 2, "link");
- Link->addIncoming(Head, Entry);
- Value *Node = Builder.CreateLoad(Ptr, Link, "node");
- Checker.emitCheck(Builder.CreateIsNull(Node), InvalidAddress, {Line});
- Value *Stored = Builder.CreateLoad(Ptr, Builder.CreateStructGEP(NodeTy, Node, 0));
- Value *NextLink = Builder.CreateStructGEP(NodeTy, Node, 1);
- Link->addIncoming(NextLink, Builder.GetInsertBlock());
- Builder.CreateCondBr(Builder.CreateICmpEQ(Stored, Address), Found, Loop);
- Builder.SetInsertPoint(Found);
- Builder.CreateRet(Link);
-}
-
-void MemoryHandler::buildAllocate() {
- auto *Ptr = PointerType::getUnqual(Context);
- Value *Size = AllocateFn->getArg(0), *Line = AllocateFn->getArg(1);
- auto *Zero = BasicBlock::Create(Context, "zero_size", AllocateFn);
- auto *Allocate = BasicBlock::Create(Context, "allocate", AllocateFn);
- Builder.CreateCondBr(Builder.CreateICmpEQ(Size, ConstantInt::get(SizeTy, 0)), Zero, Allocate);
- Builder.SetInsertPoint(Zero);
- Builder.CreateRet(ConstantPointerNull::get(Ptr));
- Builder.SetInsertPoint(Allocate);
- Value *NodeSize = Builder.CreateIntCast(Types.getSizeOfConstant(NodeTy), SizeTy, false);
- Value *Node = Builder.CreateCall(Malloc, {NodeSize}, "new_node");
- Checker.emitCheck(Builder.CreateIsNull(Node), TrackingError, {Line});
- Value *Address = Builder.CreateCall(Malloc, {Size}, "allocation");
- Value *Failed = Builder.CreateIsNull(Address);
- auto *Cleanup = BasicBlock::Create(Context, "cleanup_node", AllocateFn);
- auto *Checked = BasicBlock::Create(Context, "check_allocation", AllocateFn);
- Builder.CreateCondBr(Failed, Cleanup, Checked);
- Builder.SetInsertPoint(Cleanup);
- Builder.CreateCall(Free, {Node});
- Builder.CreateBr(Checked);
- Builder.SetInsertPoint(Checked);
- Checker.emitCheck(Failed, AllocationError, {Line});
- Builder.CreateStore(Address, Builder.CreateStructGEP(NodeTy, Node, 0));
- Builder.CreateStore(Builder.CreateLoad(Ptr, Head), Builder.CreateStructGEP(NodeTy, Node, 1));
- Builder.CreateStore(Node, Head);
- Builder.CreateRet(Address);
-}
-
-void MemoryHandler::buildRelease() {
- auto *Ptr = PointerType::getUnqual(Context);
- Value *Address = ReleaseFn->getArg(0), *Line = ReleaseFn->getArg(1);
- auto *Done = BasicBlock::Create(Context, "done", ReleaseFn);
- auto *Release = BasicBlock::Create(Context, "release", ReleaseFn);
- Builder.CreateCondBr(Builder.CreateIsNull(Address), Done, Release);
- Builder.SetInsertPoint(Release);
- Value *Link = Exceptions.emitCall(FindFn, {Address, Line}, "link");
- Value *Node = Builder.CreateLoad(Ptr, Link);
- Value *Next = Builder.CreateLoad(Ptr, Builder.CreateStructGEP(NodeTy, Node, 1));
- Builder.CreateStore(Next, Link);
- Builder.CreateCall(Free, {Address});
- Builder.CreateCall(Free, {Node});
- Builder.CreateBr(Done);
- Builder.SetInsertPoint(Done);
- Builder.CreateRet(Address);
-}
-
-Value *MemoryHandler::emitAllocate(Value *Size, int Line) {
- ensureRuntime();
- return Exceptions.emitCall(AllocateFn, {Size, Checker.lineValue(Line)}, "allocated");
-}
-
-Value *MemoryHandler::emitRelease(Value *Address, int Line) {
- ensureRuntime();
- return Exceptions.emitCall(ReleaseFn, {Address, Checker.lineValue(Line)}, "released");
-}
-
-void MemoryHandler::buildResize() {
- auto *Ptr = PointerType::getUnqual(Context);
- Value *Address = ResizeFn->getArg(0), *Size = ResizeFn->getArg(1), *Line = ResizeFn->getArg(2);
- auto *Allocate = BasicBlock::Create(Context, "allocate", ResizeFn);
- auto *Validate = BasicBlock::Create(Context, "validate", ResizeFn);
- auto *Release = BasicBlock::Create(Context, "release", ResizeFn);
- auto *Resize = BasicBlock::Create(Context, "resize", ResizeFn);
- Builder.CreateCondBr(Builder.CreateIsNull(Address), Allocate, Validate);
- Builder.SetInsertPoint(Allocate);
- Builder.CreateRet(Exceptions.emitCall(AllocateFn, {Size, Line}, "allocation"));
- Builder.SetInsertPoint(Validate);
- Value *Link = Exceptions.emitCall(FindFn, {Address, Line}, "link");
- Value *Node = Builder.CreateLoad(Ptr, Link);
- Builder.CreateCondBr(Builder.CreateICmpEQ(Size, ConstantInt::get(SizeTy, 0)), Release, Resize);
- Builder.SetInsertPoint(Release);
- Exceptions.emitCall(ReleaseFn, {Address, Line});
- Builder.CreateRet(ConstantPointerNull::get(Ptr));
- Builder.SetInsertPoint(Resize);
- Value *NewAddress = Builder.CreateCall(Realloc, {Address, Size}, "resized");
- // libc preserves the original block on nonzero-size failure. Leave the
- // tracking entry untouched until the check has succeeded as well.
- Checker.emitCheck(Builder.CreateIsNull(NewAddress), AllocationError, {Line});
- Builder.CreateStore(NewAddress, Builder.CreateStructGEP(NodeTy, Node, 0));
- Builder.CreateRet(NewAddress);
-}
-
-Value *MemoryHandler::emitResize(Value *Address, Value *Size, int Line) {
- ensureRuntime();
- return Exceptions.emitCall(ResizeFn, {Address, Size, Checker.lineValue(Line)}, "resized");
-}
-
-void MemoryHandler::emitValidate(Value *Address, int Line) {
- ensureRuntime();
- Exceptions.emitCall(FindFn, {Address, Checker.lineValue(Line)});
-}