aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/Builtins.h1
-rw-r--r--lib/CodeGen/ExpressionGen.cc7
-rw-r--r--lib/CodeGen/MemoryHandler.cc34
3 files changed, 42 insertions, 0 deletions
diff --git a/lib/CodeGen/Builtins.h b/lib/CodeGen/Builtins.h
index 69361cf..b74afc4 100644
--- a/lib/CodeGen/Builtins.h
+++ b/lib/CodeGen/Builtins.h
@@ -27,6 +27,7 @@ inline constexpr BuiltinInfo Builtins[] = {
{"STR_TO_NUM", 1, "REAL"},
{"EOF", 1, "BOOLEAN"},
{"MALLOC", 1, "C_TYPE(\"void*\")"},
+ {"REALLOC", 2, "C_TYPE(\"void*\")"},
{"FREE", 1, "C_TYPE(\"void*\")"},
};
diff --git a/lib/CodeGen/ExpressionGen.cc b/lib/CodeGen/ExpressionGen.cc
index 0a24c8d..9ea79d8 100644
--- a/lib/CodeGen/ExpressionGen.cc
+++ b/lib/CodeGen/ExpressionGen.cc
@@ -192,6 +192,13 @@ Value *CodeGen::emitCall(const std::string &Callee,
if (!Size) return nullptr;
return Memory->emitAllocate(Size, Line);
}
+ if (Name == "REALLOC") {
+ Value *Address = emitCoercedExpr(ArgExprs[0].get(), resolveType("C_TYPE(\"void*\")"));
+ if (!Address) return nullptr;
+ Value *Size = emitAllocationSize(ArgExprs[1].get());
+ if (!Size) return nullptr;
+ return Memory->emitResize(Address, Size, Line);
+ }
if (Name == "FREE") {
Value *Address = emitCoercedExpr(ArgExprs[0].get(), resolveType("C_TYPE(\"void*\")"));
if (!Address) return nullptr;
diff --git a/lib/CodeGen/MemoryHandler.cc b/lib/CodeGen/MemoryHandler.cc
index fc6d982..07fe6f6 100644
--- a/lib/CodeGen/MemoryHandler.cc
+++ b/lib/CodeGen/MemoryHandler.cc
@@ -27,6 +27,7 @@ void MemoryHandler::ensureRuntime() {
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",
@@ -39,6 +40,8 @@ void MemoryHandler::ensureRuntime() {
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
@@ -118,3 +121,34 @@ Value *MemoryHandler::emitRelease(Value *Address, int Line) {
ensureRuntime();
return Exceptions.emitCall(ReleaseFn, {Address, Builder.getInt32(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, Builder.getInt32(Line)}, "resized");
+}