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/RuntimeCheck.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/RuntimeCheck.h')
| -rw-r--r-- | include/cps/RuntimeCheck.h | 28 |
1 files changed, 8 insertions, 20 deletions
diff --git a/include/cps/RuntimeCheck.h b/include/cps/RuntimeCheck.h index 51a07aa..d9a69b6 100644 --- a/include/cps/RuntimeCheck.h +++ b/include/cps/RuntimeCheck.h @@ -7,24 +7,18 @@ namespace cps { +class ExceptionHandler; + class RuntimeCheck { - llvm::Module &TheModule; llvm::LLVMContext &TheContext; llvm::IRBuilder<> &Builder; - - llvm::FunctionCallee PrintfFunc; - llvm::FunctionCallee ExitFunc; - llvm::Value *DivZeroMsg; - llvm::Value *OutOfBoundsMsg; - llvm::Value *EnumRangeMsg; - llvm::Value *NullDerefMsg; - llvm::Value *ArrayArgBoundsMsg; - - void setupExternalFunctions(); - void emitErrorAndExit(llvm::Value *Condition, llvm::Value *Msg, int Line); + ExceptionHandler &Exceptions; public: - RuntimeCheck(llvm::Module &M, llvm::LLVMContext &C, llvm::IRBuilder<> &B); + RuntimeCheck(llvm::LLVMContext &C, llvm::IRBuilder<> &B, ExceptionHandler &EH); + + // Split the block, throwing an anonymous exception when Condition is true. + void emitCheck(llvm::Value *Condition); void emitDivZeroCheck(llvm::Value *Divisor, int Line); void emitIndexCheck(llvm::Value *Index, llvm::Value *Lower, llvm::Value *Upper, int Line); @@ -33,7 +27,7 @@ public: void emitEnumRangeCheck(llvm::Value *Ordinal, uint64_t ValueCount, const std::string &TypeName, int Line); - // Dereferencing an unset (null) pointer dies instead of segfaulting. + // Dereferencing an unset (null) pointer throws instead of segfaulting. void emitNullDerefCheck(llvm::Value *Ptr, int Line); // A bounded array parameter is a contract: the argument's runtime bounds @@ -41,12 +35,6 @@ public: void emitArrayArgBoundsCheck(llvm::Value *ActualLower, llvm::Value *ActualUpper, int64_t DeclaredLower, int64_t DeclaredUpper, int Line); - // Runtime-computed variant: FmtArgs are the printf varargs after Msg - // (e.g. {i32 line, ptr filename}). Needed when the failure site is inside - // a synthesized helper function, where the line number is an argument - // rather than a compile-time constant. - void emitErrorAndExit(llvm::Value *Condition, llvm::Value *Msg, - llvm::ArrayRef<llvm::Value *> FmtArgs); }; } |
