aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-17 06:54:32 +0000
committer_ov4 <ov4@ov4.org>2026-10-17 06:54:32 +0000
commit74b6d06711afd3efbbc47436f1491900994313f3 (patch)
treeb9050214b147cd2b1b54fd27e75d669bf6146e48 /lib/CodeGen
parent39661855c0816ac248be437704c76f58359cb5f0 (diff)
feat(classes): allocate objects with NEW and rebind named class variables
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'lib/CodeGen')
-rw-r--r--lib/CodeGen/ArrayHandler.cc5
-rw-r--r--lib/CodeGen/CodeGen.cc2
-rw-r--r--lib/CodeGen/ConstructorGen.cc39
-rw-r--r--lib/CodeGen/Designator.cc7
-rw-r--r--lib/CodeGen/ExpressionGen.cc4
-rw-r--r--lib/CodeGen/FunctionGen.cc9
-rw-r--r--lib/CodeGen/StatementGen.cc9
-rw-r--r--lib/CodeGen/TypeSystem.cc3
-rw-r--r--lib/CodeGen/ValueTypeGen.cc11
9 files changed, 68 insertions, 21 deletions
diff --git a/lib/CodeGen/ArrayHandler.cc b/lib/CodeGen/ArrayHandler.cc
index 337e5f4..8da6cd3 100644
--- a/lib/CodeGen/ArrayHandler.cc
+++ b/lib/CodeGen/ArrayHandler.cc
@@ -241,10 +241,7 @@ void ArrayHandler::emitArrayAssign(ArrayAssignStmtAST *Stmt, CodeGen &CG) {
Stmt->getLine(), CG, ElemTypeName);
if (!ElemPtr) return;
- Value *Val = CG.emitCoercedExpr(Stmt->getExpr(), Types.resolve(ElemTypeName));
- if (!Val) return;
-
- Builder->CreateStore(Val, ElemPtr);
+ CG.emitAssignment({ElemPtr, ElemTypeName}, Stmt->getExpr());
}
Value *ArrayHandler::emitElementAddress(const std::string &Name,
diff --git a/lib/CodeGen/CodeGen.cc b/lib/CodeGen/CodeGen.cc
index 01393a9..68dec5c 100644
--- a/lib/CodeGen/CodeGen.cc
+++ b/lib/CodeGen/CodeGen.cc
@@ -266,7 +266,7 @@ bool CodeGen::marshalCallArgs(const std::string &Callee,
TypeName.c_str(), Info->TypeName.c_str());
return false;
}
- Out.push_back(Info->Storage);
+ Out.push_back(symbolAddress(*Info));
} else {
Value *V = emitCoercedExpr(ArgExpr, resolveType(TypeName));
if (!V) return false;
diff --git a/lib/CodeGen/ConstructorGen.cc b/lib/CodeGen/ConstructorGen.cc
index 0d4d732..f726590 100644
--- a/lib/CodeGen/ConstructorGen.cc
+++ b/lib/CodeGen/ConstructorGen.cc
@@ -1,4 +1,8 @@
#include "cps/CodeGen.h"
+#include "cps/MemoryHandler.h"
+#include "cps/TypeAST.h"
+#include <climits>
+#include <cstddef>
using namespace llvm;
using namespace cps;
@@ -37,3 +41,38 @@ bool CodeGen::emitConstruct(const std::string &TypeName, Value *Addr,
bool CodeGen::emitDefaultConstruct(const std::string &TypeName, Value *Addr, int Line) {
return emitConstruct(TypeName, Addr, {}, Line);
}
+
+Value *CodeGen::symbolAddress(const SymbolInfo &Info) {
+ if (!Info.IsReference) return Info.Storage;
+ return Builder->CreateLoad(PointerType::getUnqual(*TheContext), Info.Storage, "object_address");
+}
+
+void CodeGen::emitAssignment(const LValueInfo &Target, ExprAST *Expr, const SymbolInfo *Symbol) {
+ const TypeInfo *Info = resolveType(Target.TypeName);
+ if (auto *New = dynamic_cast<NewExprAST*>(Expr)) {
+ SaveAndRestore<int> Location(DiagnosticLine, New->getLine());
+ const TypeInfo *Class = resolveType(New->getClassName());
+ if (!Class || !Class->IsClass) {
+ reportError("NEW requires a class type: %s", New->getClassName().c_str());
+ return;
+ }
+ if (!Info || !Info->sameType(Class)) {
+ reportError("NEW target must have type %s", Class->Name.c_str());
+ return;
+ }
+ Value *Size = Builder->CreateIntCast(Types->getSizeOfConstant(Class->LLVMType),
+ Type::getIntNTy(*TheContext, sizeof(std::size_t) * CHAR_BIT), false);
+ Value *Object = Memory->emitAllocate(Size, New->getLine());
+ Builder->CreateStore(Types->getZeroValue(Class->Name), Object);
+ if (!emitConstruct(Class->Name, Object, New->getArgs(), New->getLine())) return;
+ if (Symbol && Symbol->IsReference) {
+ Builder->CreateStore(Object, Symbol->Storage);
+ } else {
+ Value *Val = Builder->CreateLoad(Class->LLVMType, Object);
+ Builder->CreateStore(Val, Target.Addr);
+ }
+ return;
+ }
+ Value *Val = emitCoercedExpr(Expr, Info);
+ if (Val) Builder->CreateStore(Val, Target.Addr);
+}
diff --git a/lib/CodeGen/Designator.cc b/lib/CodeGen/Designator.cc
index 1ebd158..5f54a87 100644
--- a/lib/CodeGen/Designator.cc
+++ b/lib/CodeGen/Designator.cc
@@ -24,7 +24,8 @@ void CodeGen::runTypePrePass(const std::vector<std::unique_ptr<StmtAST>> &Statem
else if (auto *P = dynamic_cast<PointerTypeDeclAST*>(S.get()))
Ok = Types->declareUserType(P->getName(), TypeKind::Pointer, Err);
else if (auto *R = dynamic_cast<RecordTypeDeclAST*>(S.get()))
- Ok = Types->declareUserType(R->getName(), TypeKind::Record, Err);
+ Ok = Types->declareUserType(R->getName(), TypeKind::Record, Err,
+ dynamic_cast<ClassTypeDeclAST*>(R) != nullptr);
if (!Ok) reportError("%s", Err.c_str());
}
@@ -120,7 +121,7 @@ bool CodeGen::emitLValue(ExprAST *E, LValueInfo &Out) {
reportError("Whole array %s is not an assignable location; index it", Var->getName().c_str());
return false;
}
- Out.Addr = Info->Storage;
+ Out.Addr = symbolAddress(*Info);
Out.TypeName = Info->TypeName;
return true;
}
@@ -148,7 +149,7 @@ bool CodeGen::emitLValue(ExprAST *E, LValueInfo &Out) {
if (!requireWritable(*Info, D->getBaseName())) return false;
const auto &Accesses = D->getAccesses();
- Value *Addr = Info->Storage;
+ Value *Addr = symbolAddress(*Info);
std::string TypeName = Info->TypeName;
size_t Start = 0;
diff --git a/lib/CodeGen/ExpressionGen.cc b/lib/CodeGen/ExpressionGen.cc
index fde948c..ba5e329 100644
--- a/lib/CodeGen/ExpressionGen.cc
+++ b/lib/CodeGen/ExpressionGen.cc
@@ -51,7 +51,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
}
if (Info->ConstantValue) return Info->ConstantValue;
if (Info->IsArray) {
- return Info->Storage;
+ return symbolAddress(*Info);
}
const TypeInfo *TypeInfo = resolveType(Info->TypeName);
@@ -60,7 +60,7 @@ Value *CodeGen::emitExpr(ExprAST *Expr) {
return nullptr;
}
- Value *Loaded = Builder->CreateLoad(TypeInfo->LLVMType, Info->Storage, Var->getName().c_str());
+ Value *Loaded = Builder->CreateLoad(TypeInfo->LLVMType, symbolAddress(*Info), Var->getName().c_str());
if (TypeInfo->isString()) {
Loaded = emitStringNullGuard(Loaded);
}
diff --git a/lib/CodeGen/FunctionGen.cc b/lib/CodeGen/FunctionGen.cc
index d5bc5d4..e344410 100644
--- a/lib/CodeGen/FunctionGen.cc
+++ b/lib/CodeGen/FunctionGen.cc
@@ -90,7 +90,14 @@ void FunctionGen::createArgumentAllocas(Function *F, const std::vector<ParamDecl
AllocaInst *Alloca = TmpB.CreateAlloca(ArgType, nullptr, P.Name);
Builder.CreateStore(ArgVal, Alloca);
- Symbols[P.Name] = {Alloca, P.TypeName, false};
+ const TypeInfo *Info = Types.resolve(P.TypeName);
+ if (Info && Info->IsClass) {
+ AllocaInst *Slot = TmpB.CreateAlloca(PointerType::getUnqual(Context), nullptr, P.Name + ".ref");
+ Builder.CreateStore(Alloca, Slot);
+ Symbols[P.Name] = {Slot, P.TypeName, false, nullptr, 0, true};
+ } else {
+ Symbols[P.Name] = {Alloca, P.TypeName, false};
+ }
}
}
diff --git a/lib/CodeGen/StatementGen.cc b/lib/CodeGen/StatementGen.cc
index 2443877..bd1f7c5 100644
--- a/lib/CodeGen/StatementGen.cc
+++ b/lib/CodeGen/StatementGen.cc
@@ -128,10 +128,7 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
return;
}
- Value *Val = emitCoercedExpr(Assign->getExpr(), resolveType(Info->TypeName));
- if (!Val) return;
-
- Builder->CreateStore(Val, Info->Storage);
+ emitAssignment({symbolAddress(*Info), Info->TypeName}, Assign->getExpr(), Info);
return;
}
@@ -296,9 +293,7 @@ void CodeGen::emitStmt(StmtAST *Stmt) {
if (auto *DA = dynamic_cast<DesignatorAssignStmtAST*>(Stmt)) {
LValueInfo LV;
if (!emitLValue(DA->getTarget(), LV)) return;
- Value *Val = emitCoercedExpr(DA->getExpr(), resolveType(LV.TypeName));
- if (!Val) return;
- Builder->CreateStore(Val, LV.Addr);
+ emitAssignment(LV, DA->getExpr());
return;
}
}
diff --git a/lib/CodeGen/TypeSystem.cc b/lib/CodeGen/TypeSystem.cc
index f4620dc..27814c2 100644
--- a/lib/CodeGen/TypeSystem.cc
+++ b/lib/CodeGen/TypeSystem.cc
@@ -129,7 +129,7 @@ const TypeInfo *TypeSystem::registerType(const std::string &TypeName,
return &Result.first->second;
}
-bool TypeSystem::declareUserType(const std::string &Name, TypeKind Kind, std::string &Err) {
+bool TypeSystem::declareUserType(const std::string &Name, TypeKind Kind, std::string &Err, bool IsClass) {
if (Types.count(Name)) {
Err = "Type " + Name + " is already defined";
return false;
@@ -157,6 +157,7 @@ bool TypeSystem::declareUserType(const std::string &Name, TypeKind Kind, std::st
}
registerType(Name, LLVMType, Kind);
+ Types.find(Name)->second.IsClass = IsClass;
return true;
}
diff --git a/lib/CodeGen/ValueTypeGen.cc b/lib/CodeGen/ValueTypeGen.cc
index baa384c..fbe6dd5 100644
--- a/lib/CodeGen/ValueTypeGen.cc
+++ b/lib/CodeGen/ValueTypeGen.cc
@@ -279,8 +279,15 @@ void CodeGen::emitDeclareStmt(DeclareStmtAST *Stmt) {
Builder->CreateStore(InitVal, Alloca);
}
- registerSymbol(Stmt->getName(), Alloca, Info->Name, false);
- if (Stmt->hasParens() && !ClassMethods.count(Info->Name)) {
+ Value *Storage = Alloca;
+ if (Info->IsClass) {
+ Storage = CreateEntryBlockAlloca(TheFunction, PointerType::getUnqual(*TheContext),
+ Stmt->getName() + ".ref");
+ Builder->CreateStore(Alloca, Storage);
+ }
+ registerSymbol(Stmt->getName(), Storage, Info->Name, false);
+ Symbols.find(Stmt->getName())->second.IsReference = Info->IsClass;
+ if (Stmt->hasParens() && !Info->IsClass) {
reportError("Constructor arguments require a class type");
return;
}