aboutsummaryrefslogtreecommitdiff
path: root/include/cps/FileHandler.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/cps/FileHandler.h')
-rw-r--r--include/cps/FileHandler.h75
1 files changed, 75 insertions, 0 deletions
diff --git a/include/cps/FileHandler.h b/include/cps/FileHandler.h
new file mode 100644
index 0000000..aaad6a0
--- /dev/null
+++ b/include/cps/FileHandler.h
@@ -0,0 +1,75 @@
+#pragma once
+#include "cps/FileMode.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+
+namespace cps {
+
+class RuntimeCheck;
+
+// Emits the text-file runtime: a fixed-size open-file table plus internal
+// __cps_file_* helper functions, synthesized once on first use so programs
+// without file statements keep their IR unchanged. The table is keyed by
+// filename *content* (strcmp) — pseudocode STRING equality is pointer
+// identity, so the same file may be named by many different buffers.
+// Leaf module: methods only take and return llvm::Value*s; expression
+// evaluation, type coercion and the symbol table stay in CodeGen.
+class FileHandler {
+ llvm::LLVMContext &Context;
+ llvm::IRBuilder<> &Builder;
+ llvm::Module &Module;
+ RuntimeCheck &Checker;
+
+ static constexpr uint64_t TableSize = 16;
+ bool RuntimeEmitted = false;
+
+ // libc — declared lazily on first file use
+ llvm::FunctionCallee FopenFunc, FcloseFunc, FgetcFunc, UngetcFunc,
+ FputsFunc, FputcFunc, MallocFunc, ReallocFunc,
+ StrcmpFunc;
+
+ // open-file table
+ llvm::GlobalVariable *FileNames = nullptr; // [TableSize x ptr] STRING passed to OPENFILE
+ llvm::GlobalVariable *FileHandles = nullptr; // [TableSize x ptr] FILE*
+ llvm::GlobalVariable *FileModes = nullptr; // [TableSize x i8] 0 = free slot, else FileMode
+
+ llvm::Value *ModeReadStr = nullptr, *ModeWriteStr = nullptr, *ModeAppendStr = nullptr;
+ llvm::Value *ErrOpenFail = nullptr, *ErrAlreadyOpen = nullptr, *ErrTableFull = nullptr,
+ *ErrNotOpen = nullptr, *ErrNotRead = nullptr, *ErrNotWrite = nullptr,
+ *ErrPastEof = nullptr;
+
+ // synthesized helpers (internal linkage; pseudocode identifiers cannot
+ // start with '_', so these names are un-collidable)
+ llvm::Function *FindFn = nullptr, *OpenFn = nullptr, *ReadFn = nullptr,
+ *WriteFn = nullptr, *CloseFn = nullptr, *EofFn = nullptr;
+
+ void setupExternalFunctions();
+ void setupGlobals();
+ void ensureRuntime();
+
+ llvm::Function *createHelper(const char *Name, llvm::FunctionType *FT);
+ llvm::Value *emitSlotGEP(llvm::GlobalVariable *Table, llvm::Type *ElemTy, llvm::Value *Idx);
+ llvm::Value *emitLookupOrFail(llvm::Value *Name, llvm::Value *Line);
+ void buildFindFn();
+ void buildOpenFn();
+ void buildReadFn();
+ void buildWriteFn();
+ void buildCloseFn();
+ void buildEofFn();
+
+public:
+ FileHandler(llvm::LLVMContext &Ctx, llvm::IRBuilder<> &B, llvm::Module &M,
+ RuntimeCheck &RC);
+
+ // NameStr/DataStr are already-coerced STRING ptrs; Line is the statement's
+ // source line for runtime diagnostics. All methods null-check and bail;
+ // the caller (CodeGen) does the diagnostics.
+ void emitOpen(llvm::Value *NameStr, FileMode Mode, int Line);
+ llvm::Value *emitRead(llvm::Value *NameStr, int Line); // returns STRING ptr
+ void emitWrite(llvm::Value *NameStr, llvm::Value *DataStr, int Line);
+ void emitClose(llvm::Value *NameStr, int Line);
+ llvm::Value *emitEof(llvm::Value *NameStr, int Line); // returns i1
+};
+
+} // namespace cps