From b8d6ba9033ab80c017989d6b8e0f0bd56b3e918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Grodzi=C5=84ski?= Date: Mon, 11 Aug 2025 21:29:20 +0900 Subject: [PATCH] Build struct member assignment --- samples/test.brc | 1 + src/Compiler/ModuleBuilder.cpp | 76 +++++++++++++++----- src/Compiler/ModuleBuilder.h | 6 +- src/Parser/Statement/StatementAssignment.cpp | 8 +++ src/Parser/Statement/StatementAssignment.h | 10 +++ 5 files changed, 81 insertions(+), 20 deletions(-) diff --git a/samples/test.brc b/samples/test.brc index d5b647e..2862269 100644 --- a/samples/test.brc +++ b/samples/test.brc @@ -12,6 +12,7 @@ User blob main fun -> u32 us User + us<- 5 ret 0 ; \ No newline at end of file diff --git a/src/Compiler/ModuleBuilder.cpp b/src/Compiler/ModuleBuilder.cpp index 598f78d..8c1f0f0 100644 --- a/src/Compiler/ModuleBuilder.cpp +++ b/src/Compiler/ModuleBuilder.cpp @@ -168,15 +168,17 @@ void ModuleBuilder::buildBlob(shared_ptr statement) { llvm::StructType *structType = llvm::StructType::create(*context, statement->getIdentifier()); // Generate types for body + vector memberNames; vector types; for (pair> &variable: statement->getVariables()) { + memberNames.push_back(variable.first); llvm::Type *type = typeForValueType(variable.second); if (type == nullptr) return; types.push_back(type); } structType->setBody(types, false); - if (!setStruct(statement->getIdentifier(), structType)) + if (!registerStruct(statement->getIdentifier(), structType, memberNames)) return; } @@ -226,18 +228,37 @@ void ModuleBuilder::buildAssignment(shared_ptr statement) { llvm::Value *value = valueForExpression(statement->getExpression()); - if (statement->getIndexExpression()) { - llvm::Value *indexValue = valueForExpression(statement->getIndexExpression()); - llvm::Value *index[] = { - builder->getInt32(0), - indexValue - }; - llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType(); - llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", statement->getName())); + switch (statement->getAssignmentKind()) { + case StatementAssignmentKind::VARIABLE: { + builder->CreateStore(value, alloca); + break; + } + case StatementAssignmentKind::DATA: { + llvm::Value *indexValue = valueForExpression(statement->getIndexExpression()); + llvm::Value *index[] = { + builder->getInt32(0), + indexValue + }; + llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType(); + llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", statement->getName())); - builder->CreateStore(value, elementPtr); - } else { - builder->CreateStore(value, alloca); + builder->CreateStore(value, elementPtr); + break; + } + case StatementAssignmentKind::BLOB: { + llvm::StructType *structType = (llvm::StructType *)alloca->getAllocatedType(); + string structName = string(structType->getName()); + optional memberIndex = getMemberIndex(structName, statement->getMemberName()); + if (!memberIndex) + return; + llvm::Value *index[] = { + builder->getInt32(0), + builder->getInt32(*memberIndex) + }; + llvm::Value *elementPtr = builder->CreateGEP(structType, alloca, index); + builder->CreateStore(value, elementPtr); + break; + } } } @@ -701,21 +722,23 @@ llvm::InlineAsm *ModuleBuilder::getRawFun(string name) { return nullptr; } -bool ModuleBuilder::setStruct(string name, llvm::StructType *structType) { - if (scopes.top().structTypeMap[name] != nullptr) { - markError(0, 0, format("Type \"{}\" already defined in scope", name)); +bool ModuleBuilder::registerStruct(string structName, llvm::StructType *structType, vector memberNames) { + if (scopes.top().structTypeMap[structName] != nullptr) { + markError(0, 0, format("Blob \"{}\" already defined in scope",structName)); return false; } - scopes.top().structTypeMap[name] = structType; + scopes.top().structTypeMap[structName] = structType; + scopes.top().structMembersMap[structName] = memberNames; + return true; } -llvm::StructType *ModuleBuilder::getStructType(string name) { +llvm::StructType *ModuleBuilder::getStructType(string structName) { stack scopes = this->scopes; while (!scopes.empty()) { - llvm::StructType *structType = scopes.top().structTypeMap[name]; + llvm::StructType *structType = scopes.top().structTypeMap[structName]; if (structType != nullptr) return structType; scopes.pop(); @@ -724,6 +747,23 @@ llvm::StructType *ModuleBuilder::getStructType(string name) { return nullptr; } +optional ModuleBuilder::getMemberIndex(string structName, string memberName) { + stack scopes = this->scopes; + + while (!scopes.empty()) { + if (scopes.top().structMembersMap.contains(structName)) { + vector memberNames = scopes.top().structMembersMap[structName]; + for (int i=0; i valueType, int count) { if (valueType == nullptr) { markError(0, 0, "Missing type"); diff --git a/src/Compiler/ModuleBuilder.h b/src/Compiler/ModuleBuilder.h index d63b0a7..dcf55b3 100644 --- a/src/Compiler/ModuleBuilder.h +++ b/src/Compiler/ModuleBuilder.h @@ -45,6 +45,7 @@ typedef struct { map funMap; map rawFunMap; map structTypeMap; + map> structMembersMap; } Scope; class ModuleBuilder { @@ -104,8 +105,9 @@ private: bool setRawFun(string name, llvm::InlineAsm *rawFun); llvm::InlineAsm *getRawFun(string name); - bool setStruct(string name, llvm::StructType *structType); - llvm::StructType *getStructType(string name); + bool registerStruct(string structName, llvm::StructType *structType, vector memberNames); + llvm::StructType *getStructType(string structName); + optional getMemberIndex(string structName, string memberName); llvm::Type *typeForValueType(shared_ptr valueType, int count = 0); diff --git a/src/Parser/Statement/StatementAssignment.cpp b/src/Parser/Statement/StatementAssignment.cpp index ae0d24f..c63e13d 100644 --- a/src/Parser/Statement/StatementAssignment.cpp +++ b/src/Parser/Statement/StatementAssignment.cpp @@ -3,6 +3,10 @@ StatementAssignment::StatementAssignment(string name, shared_ptr indexExpression, shared_ptr expression): Statement(StatementKind::ASSIGNMENT), name(name), indexExpression(indexExpression), expression(expression) { } +StatementAssignmentKind StatementAssignment::getAssignmentKind() { + return assignmentKind; +} + string StatementAssignment::getName() { return name; } @@ -13,4 +17,8 @@ shared_ptr StatementAssignment::getIndexExpression() { shared_ptr StatementAssignment::getExpression() { return expression; +} + +string StatementAssignment::getMemberName() { + return memberName; } \ No newline at end of file diff --git a/src/Parser/Statement/StatementAssignment.h b/src/Parser/Statement/StatementAssignment.h index 0bb7f63..bc541ae 100644 --- a/src/Parser/Statement/StatementAssignment.h +++ b/src/Parser/Statement/StatementAssignment.h @@ -2,15 +2,25 @@ class Expression; +enum class StatementAssignmentKind { + VARIABLE, + DATA, + BLOB +}; + class StatementAssignment: public Statement { private: + StatementAssignmentKind assignmentKind; string name; shared_ptr indexExpression; shared_ptr expression; + string memberName; public: StatementAssignment(string name, shared_ptr indexExpressio, shared_ptr expression); + StatementAssignmentKind getAssignmentKind(); string getName(); shared_ptr getIndexExpression(); shared_ptr getExpression(); + string getMemberName(); }; \ No newline at end of file