From f2b051ae3e28135cc02589f3f698c43743cca48e Mon Sep 17 00:00:00 2001 From: _ov4 Date: Fri, 27 Mar 2026 01:50:32 +0000 Subject: feat: generalize typed array support --- include/cps/AST.h | 7 +++++ include/cps/ArrayHandler.h | 41 +++++++++++++++++--------- include/cps/CodeGen.h | 18 ++++++++++++ include/cps/FunctionGen.h | 13 +++++++-- include/cps/Lexer.h | 3 ++ include/cps/Parser.h | 2 ++ include/cps/TypeSystem.h | 71 ++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 139 insertions(+), 16 deletions(-) create mode 100644 include/cps/TypeSystem.h (limited to 'include') diff --git a/include/cps/AST.h b/include/cps/AST.h index f07e937..f24d987 100644 --- a/include/cps/AST.h +++ b/include/cps/AST.h @@ -32,6 +32,13 @@ public: bool getVal() const { return Val; } }; +class CharExprAST : public ExprAST { + char Val; +public: + CharExprAST(char Val) : Val(Val) {} + char getVal() const { return Val; } +}; + class StringExprAST : public ExprAST { std::string Val; public: diff --git a/include/cps/ArrayHandler.h b/include/cps/ArrayHandler.h index 1ee91db..f15004f 100644 --- a/include/cps/ArrayHandler.h +++ b/include/cps/ArrayHandler.h @@ -4,6 +4,8 @@ #include "llvm/IR/Module.h" #include "cps/AST.h" #include "cps/RuntimeCheck.h" +#include "cps/TypeSystem.h" +#include #include #include #include @@ -11,11 +13,13 @@ namespace cps { struct ArrayMetadata { - int Rank; - llvm::Type* ElementType; + int Rank = 0; + std::string ElementTypeName; + llvm::Type *ElementType = nullptr; + uint64_t ElementSize = 0; std::vector LowerBounds; std::vector UpperBounds; - std::vector Multipliers; + std::vector Multipliers; }; class CodeGen; @@ -25,6 +29,8 @@ class ArrayHandler { llvm::IRBuilder<> *Builder; llvm::Module *TheModule; std::map *NamedValues; + std::map *Symbols; + TypeSystem &Types; std::map ArrayTable; RuntimeCheck &RuntimeChecker; @@ -32,22 +38,31 @@ class ArrayHandler { llvm::FunctionCallee MallocFunc; llvm::FunctionCallee FreeFunc; - llvm::Value* computeFlatIndex(const std::string &Name, const std::vector &Indices); - - void emitPrintLoop(const std::string &Name, int CurrentDim, std::vector CurrentIndices, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr); + 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; + 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 &NV); + ArrayHandler(llvm::LLVMContext &C, + llvm::IRBuilder<> &B, + llvm::Module &M, + std::map &NV, + std::map &Sym, + TypeSystem &TS, + RuntimeCheck &RC); void setupExternalFunctions(); - + void emitArrayDeclare(ArrayDeclareStmtAST *Stmt, CodeGen &CG); void emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG); - ArrayHandler(llvm::LLVMContext &C, llvm::IRBuilder<> &B, llvm::Module &M, std::map &NV, RuntimeCheck &RC); - - llvm::Value* emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG); + llvm::Value *emitArrayAccess(ArrayAccessExprAST *Expr, CodeGen &CG); - bool tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG, llvm::FunctionCallee PrintfFunc, llvm::Value* FmtStr); + bool tryEmitArrayOutput(ExprAST *Expr, CodeGen &CG); }; -} +} // namespace cps diff --git a/include/cps/CodeGen.h b/include/cps/CodeGen.h index 121f30d..07ff3e8 100644 --- a/include/cps/CodeGen.h +++ b/include/cps/CodeGen.h @@ -5,6 +5,7 @@ #include "cps/AST.h" #include "cps/RuntimeCheck.h" #include "cps/FunctionGen.h" +#include "cps/TypeSystem.h" #include "cps/IntegerHandler.h" #include "cps/RealHandler.h" @@ -16,6 +17,7 @@ #include #include +#include namespace cps { @@ -26,6 +28,8 @@ class CodeGen { std::unique_ptr TheModule; std::unique_ptr> Builder; std::map NamedValues; + std::map Symbols; + std::unique_ptr Types; std::unique_ptr Arrays; std::unique_ptr RuntimeChecker; @@ -45,6 +49,7 @@ class CodeGen { llvm::Value *PrintfFormatStr; // %lld\n llvm::Value *PrintfFloatFormatStr; // %f\n llvm::Value *PrintfStringFormatStr; // %s\n + llvm::Value *PrintfCharFormatStr; // %c\n llvm::Value *ScanfFormatStr; // %lld llvm::Value *ScanfFloatFormatStr; // %lf @@ -52,9 +57,18 @@ class CodeGen { llvm::Value *TrueStr; // "TRUE" llvm::Value *FalseStr; // "FALSE" + llvm::Value *EmptyStringStr; // "" void SetupExternalFunctions(); llvm::AllocaInst *CreateEntryBlockAlloca(llvm::Function *TheFunction, const std::string &VarName); + llvm::AllocaInst *CreateEntryBlockAlloca(llvm::Function *TheFunction, llvm::Type *AllocType, const std::string &VarName); + + void registerSymbol(const std::string &Name, llvm::Value *Storage, const std::string &TypeName, bool IsArray = false); + const SymbolInfo *getSymbolInfo(const std::string &Name) const; + const TypeInfo *getExprTypeInfo(ExprAST *Expr) const; + llvm::Value *coerceValueToType(llvm::Value *Val, const TypeInfo *TargetInfo); + void emitDeclareStmt(DeclareStmtAST *Stmt); + void emitOutputValue(llvm::Value *Val, const TypeInfo *TypeInfo, bool AppendNewline = true); void emitIfStmt(IfStmtAST *Stmt); void emitWhileStmt(WhileStmtAST *Stmt); @@ -69,6 +83,10 @@ public: llvm::Value *emitExpr(ExprAST *Expr); void emitStmt(StmtAST *Stmt); + + const TypeInfo *resolveType(const std::string &TypeName) const; + llvm::Type *getLLVMType(const std::string &TypeName) const; + llvm::Value *getNamedValue(const std::string &Name) const; friend class ArrayHandler; }; diff --git a/include/cps/FunctionGen.h b/include/cps/FunctionGen.h index 84a2858..7ebb7f4 100644 --- a/include/cps/FunctionGen.h +++ b/include/cps/FunctionGen.h @@ -2,6 +2,7 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" #include "cps/FunctionAST.h" +#include "cps/TypeSystem.h" #include #include #include @@ -14,15 +15,21 @@ class FunctionGen { llvm::LLVMContext &Context; llvm::Module &Module; llvm::IRBuilder<> &Builder; + TypeSystem &Types; std::map &NamedValues; + std::map &Symbols; void createArgumentAllocas(llvm::Function *F, const std::vector> &Args); public: - FunctionGen(llvm::LLVMContext &C, llvm::Module &M, llvm::IRBuilder<> &B, - std::map &NV) - : Context(C), Module(M), Builder(B), NamedValues(NV) {} + FunctionGen(llvm::LLVMContext &C, + llvm::Module &M, + llvm::IRBuilder<> &B, + TypeSystem &TS, + std::map &NV, + std::map &Sym) + : Context(C), Module(M), Builder(B), Types(TS), NamedValues(NV), Symbols(Sym) {} llvm::Type *getLLVMType(const std::string &TypeName); diff --git a/include/cps/Lexer.h b/include/cps/Lexer.h index df84d0b..e8d2609 100644 --- a/include/cps/Lexer.h +++ b/include/cps/Lexer.h @@ -49,6 +49,8 @@ enum Token { tok_ucase = -35, tok_string_literal = -36, tok_left = -37, + tok_char_kw = -38, + tok_char_literal = -39, tok_identifier = -100, tok_number_int = -101, @@ -83,6 +85,7 @@ public: std::string StringVal; int64_t NumVal; double RealVal; + char CharVal = '\0'; int gettok(); int getLine() const { return CurrentLine; } diff --git a/include/cps/Parser.h b/include/cps/Parser.h index 877c684..19f49be 100644 --- a/include/cps/Parser.h +++ b/include/cps/Parser.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace cps { @@ -25,6 +26,7 @@ class Parser { std::unique_ptr ParseNumberExpr(); std::unique_ptr ParseIdentifierExpr(); std::unique_ptr ParseParenExpr(); + std::string ParseTypeName(bool AllowVoid = false); std::unique_ptr ParseStringBuiltin(const std::string &FuncName); diff --git a/include/cps/TypeSystem.h b/include/cps/TypeSystem.h new file mode 100644 index 0000000..32c348f --- /dev/null +++ b/include/cps/TypeSystem.h @@ -0,0 +1,71 @@ +#pragma once +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Type.h" +#include +#include +#include + +namespace cps { + +enum class TypeKind { + Integer, + Real, + Boolean, + String, + Char, + Void, + Custom +}; + +struct TypeInfo { + std::string Name; + llvm::Type *LLVMType = nullptr; + uint64_t ElementSize = 0; + TypeKind Kind = TypeKind::Custom; + bool Printable = false; + bool Builtin = false; + bool ReferenceLike = false; + + bool isNumeric() const; + bool isIntegral() const; + bool isReal() const; + bool isBoolean() const; + bool isString() const; + bool isChar() const; + bool isVoid() const; +}; + +struct SymbolInfo { + llvm::Value *Storage = nullptr; + std::string TypeName; + bool IsArray = false; +}; + +class TypeSystem { + llvm::LLVMContext &Context; + std::map Types; + + void registerBuiltins(); + +public: + explicit TypeSystem(llvm::LLVMContext &Ctx); + + const TypeInfo *resolve(const std::string &TypeName) const; + bool hasType(const std::string &TypeName) const; + + const TypeInfo *registerType(const std::string &TypeName, + llvm::Type *LLVMType, + uint64_t ElementSize, + TypeKind Kind = TypeKind::Custom, + bool Printable = false, + bool ReferenceLike = false, + bool Builtin = false); + + llvm::Type *getLLVMType(const std::string &TypeName) const; + uint64_t getElementSize(const std::string &TypeName) const; + llvm::Constant *getZeroValue(const std::string &TypeName) const; +}; + +} // namespace cps -- cgit v1.3.1-4-g156e