#pragma once #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "cps/AST.h" #include "cps/RuntimeCheck.h" #include "cps/TypeSystem.h" #include #include #include #include namespace cps { struct ArrayMetadata { int Rank = 0; std::string ElementTypeName; llvm::Type *ElementType = nullptr; llvm::Constant *ElementSizeC = nullptr; // i64 sizeof constant (target-folded) std::vector LowerBounds; std::vector UpperBounds; std::vector Multipliers; }; class CodeGen; class ArrayHandler { llvm::LLVMContext *TheContext; llvm::IRBuilder<> *Builder; llvm::Module *TheModule; std::map *Symbols; TypeSystem &Types; std::map ArrayTable; RuntimeCheck &RuntimeChecker; llvm::FunctionCallee MallocFunc; llvm::Value *computeFlatIndex(const std::string &Name, const std::vector &Indices); llvm::Value *getArrayBasePointer(const std::string &Name); llvm::Value *getElementPointer(const std::string &Name, llvm::Value *Offset); const ArrayMetadata *getMetadata(const std::string &Name) const; bool emitCheckedIndices(const std::string &Name, const std::vector> &IndexExprs, int Line, bool RequireExact, CodeGen &CG, std::vector &Out); llvm::Value *loadElement(const std::string &Name, llvm::Value *Offset, CodeGen &CG); void emitPrintLoop(const std::string &Name, int CurrentDim, std::vector CurrentIndices, CodeGen &CG); public: ArrayHandler(llvm::LLVMContext &C, llvm::IRBuilder<> &B, llvm::Module &M, std::map &Sym, TypeSystem &TS, RuntimeCheck &RC); void setupExternalFunctions(); void emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG); void emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG); llvm::Value *emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG); bool tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG); // Full-rank checked element address (bounds checks included); reports the // element type name through ElemTypeNameOut. The lvalue layer builds // field/deref accesses on top of this. llvm::Value *emitElementAddress(const std::string &Name, const std::vector> &IndexExprs, int Line, CodeGen &CG, std::string &ElemTypeNameOut); llvm::Value *emitElementAddress(ArrayAccessExprAST *Expr, CodeGen &CG, std::string &ElemTypeNameOut); // Swap in a fresh table (function bodies get their own scope, mirroring // the Symbols save/clear/restore discipline); returns the previous table. std::map exchangeTable(std::map NewTable); }; } // namespace cps