diff options
| author | _ov4 <ov4@ov4.org> | 2026-10-13 14:52:57 +0000 |
|---|---|---|
| committer | _ov4 <ov4@ov4.org> | 2026-10-13 14:52:57 +0000 |
| commit | a484f314b719aec5ed7bdc6f08403342b2125561 (patch) | |
| tree | 531e331cf823517eae4c350d37bca6a500b2de9f /include/cps/ExceptionHandler.h | |
| parent | 4297086c86f4d11e8a14b76b50705b419d6b7f13 (diff) | |
feat(compiler)!: add try-catch with C++ stack unwinding
Add TRY/CATCH/ENDTRY and anonymous THROW statements. Use LLVM exception
handling and the C++ ABI to propagate exceptions across function calls,
clean up catch state, and handle uncaught exceptions at the program boundary.
Register exception runtime symbols for the statically linked embedded runner.
Verify runtime checks, nested catches, returns, loops, and invalid syntax
with smoke programs; exercise unwinding with MCJIT, lli, and native binaries.
BREAKING CHANGE: Runtime check failures now throw anonymous exceptions and
print only a generic message when uncaught. Native binaries require linking
the C++ runtime.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'include/cps/ExceptionHandler.h')
| -rw-r--r-- | include/cps/ExceptionHandler.h | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/include/cps/ExceptionHandler.h b/include/cps/ExceptionHandler.h new file mode 100644 index 0000000..5c846ae --- /dev/null +++ b/include/cps/ExceptionHandler.h @@ -0,0 +1,48 @@ +#pragma once +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/Module.h" +#include <map> +#include <vector> + +namespace cps { + +// C++ ABI exception emission. State is keyed by function because file helper +// bodies and user functions are emitted using the same builder as their caller. +class ExceptionHandler { + struct Handler { + llvm::BasicBlock *Target; + llvm::AllocaInst *Exception; + unsigned CatchDepth; + }; + struct FunctionState { + std::vector<Handler> Handlers; + unsigned CatchDepth = 0; + }; + + llvm::LLVMContext &Context; + llvm::IRBuilder<> &Builder; + llvm::Module &Module; + std::map<llvm::Function *, FunctionState> States; + llvm::FunctionCallee Allocate, Throw, BeginCatch, EndCatch, Personality; + llvm::GlobalVariable *IntTypeInfo = nullptr; + + void ensureRuntime(); + llvm::BasicBlock *emitUnwindDestination(); + +public: + ExceptionHandler(llvm::LLVMContext &C, llvm::IRBuilder<> &B, llvm::Module &M) + : Context(C), Builder(B), Module(M) {} + + void prepareFunction(llvm::Function *F); + void pushHandler(llvm::BasicBlock *Target); + llvm::AllocaInst *popHandler(); + void beginCatch(llvm::AllocaInst *Exception); + void endCatch(); + void emitReturnCleanup(); + + llvm::Value *emitCall(llvm::FunctionCallee Callee, llvm::ArrayRef<llvm::Value *> Args, + const llvm::Twine &Name = ""); + void emitThrow(); +}; + +} // namespace cps |
