Build struct member assignment

This commit is contained in:
Rafał Grodziński
2025-08-11 21:29:20 +09:00
parent 885094eef6
commit b8d6ba9033
5 changed files with 81 additions and 20 deletions

View File

@@ -12,6 +12,7 @@ User blob
main fun -> u32 main fun -> u32
us User us User
us<- 5
ret 0 ret 0
; ;

View File

@@ -168,15 +168,17 @@ void ModuleBuilder::buildBlob(shared_ptr<StatementBlob> statement) {
llvm::StructType *structType = llvm::StructType::create(*context, statement->getIdentifier()); llvm::StructType *structType = llvm::StructType::create(*context, statement->getIdentifier());
// Generate types for body // Generate types for body
vector<string> memberNames;
vector<llvm::Type *> types; vector<llvm::Type *> types;
for (pair<string, shared_ptr<ValueType>> &variable: statement->getVariables()) { for (pair<string, shared_ptr<ValueType>> &variable: statement->getVariables()) {
memberNames.push_back(variable.first);
llvm::Type *type = typeForValueType(variable.second); llvm::Type *type = typeForValueType(variable.second);
if (type == nullptr) if (type == nullptr)
return; return;
types.push_back(type); types.push_back(type);
} }
structType->setBody(types, false); structType->setBody(types, false);
if (!setStruct(statement->getIdentifier(), structType)) if (!registerStruct(statement->getIdentifier(), structType, memberNames))
return; return;
} }
@@ -226,18 +228,37 @@ void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) {
llvm::Value *value = valueForExpression(statement->getExpression()); llvm::Value *value = valueForExpression(statement->getExpression());
if (statement->getIndexExpression()) { switch (statement->getAssignmentKind()) {
llvm::Value *indexValue = valueForExpression(statement->getIndexExpression()); case StatementAssignmentKind::VARIABLE: {
llvm::Value *index[] = { builder->CreateStore(value, alloca);
builder->getInt32(0), break;
indexValue }
}; case StatementAssignmentKind::DATA: {
llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType(); llvm::Value *indexValue = valueForExpression(statement->getIndexExpression());
llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", statement->getName())); 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); builder->CreateStore(value, elementPtr);
} else { break;
builder->CreateStore(value, alloca); }
case StatementAssignmentKind::BLOB: {
llvm::StructType *structType = (llvm::StructType *)alloca->getAllocatedType();
string structName = string(structType->getName());
optional<int> 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; return nullptr;
} }
bool ModuleBuilder::setStruct(string name, llvm::StructType *structType) { bool ModuleBuilder::registerStruct(string structName, llvm::StructType *structType, vector<string> memberNames) {
if (scopes.top().structTypeMap[name] != nullptr) { if (scopes.top().structTypeMap[structName] != nullptr) {
markError(0, 0, format("Type \"{}\" already defined in scope", name)); markError(0, 0, format("Blob \"{}\" already defined in scope",structName));
return false; return false;
} }
scopes.top().structTypeMap[name] = structType; scopes.top().structTypeMap[structName] = structType;
scopes.top().structMembersMap[structName] = memberNames;
return true; return true;
} }
llvm::StructType *ModuleBuilder::getStructType(string name) { llvm::StructType *ModuleBuilder::getStructType(string structName) {
stack<Scope> scopes = this->scopes; stack<Scope> scopes = this->scopes;
while (!scopes.empty()) { while (!scopes.empty()) {
llvm::StructType *structType = scopes.top().structTypeMap[name]; llvm::StructType *structType = scopes.top().structTypeMap[structName];
if (structType != nullptr) if (structType != nullptr)
return structType; return structType;
scopes.pop(); scopes.pop();
@@ -724,6 +747,23 @@ llvm::StructType *ModuleBuilder::getStructType(string name) {
return nullptr; return nullptr;
} }
optional<int> ModuleBuilder::getMemberIndex(string structName, string memberName) {
stack<Scope> scopes = this->scopes;
while (!scopes.empty()) {
if (scopes.top().structMembersMap.contains(structName)) {
vector<string> memberNames = scopes.top().structMembersMap[structName];
for (int i=0; i<memberNames.size(); i++) {
if (memberNames[i].compare(memberName) == 0)
return i;
}
}
scopes.pop();
}
return {};
}
llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int count) { llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int count) {
if (valueType == nullptr) { if (valueType == nullptr) {
markError(0, 0, "Missing type"); markError(0, 0, "Missing type");

View File

@@ -45,6 +45,7 @@ typedef struct {
map<string, llvm::Function*> funMap; map<string, llvm::Function*> funMap;
map<string, llvm::InlineAsm*> rawFunMap; map<string, llvm::InlineAsm*> rawFunMap;
map<string, llvm::StructType*> structTypeMap; map<string, llvm::StructType*> structTypeMap;
map<string, vector<string>> structMembersMap;
} Scope; } Scope;
class ModuleBuilder { class ModuleBuilder {
@@ -104,8 +105,9 @@ private:
bool setRawFun(string name, llvm::InlineAsm *rawFun); bool setRawFun(string name, llvm::InlineAsm *rawFun);
llvm::InlineAsm *getRawFun(string name); llvm::InlineAsm *getRawFun(string name);
bool setStruct(string name, llvm::StructType *structType); bool registerStruct(string structName, llvm::StructType *structType, vector<string> memberNames);
llvm::StructType *getStructType(string name); llvm::StructType *getStructType(string structName);
optional<int> getMemberIndex(string structName, string memberName);
llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0); llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0);

View File

@@ -3,6 +3,10 @@
StatementAssignment::StatementAssignment(string name, shared_ptr<Expression> indexExpression, shared_ptr<Expression> expression): StatementAssignment::StatementAssignment(string name, shared_ptr<Expression> indexExpression, shared_ptr<Expression> expression):
Statement(StatementKind::ASSIGNMENT), name(name), indexExpression(indexExpression), expression(expression) { } Statement(StatementKind::ASSIGNMENT), name(name), indexExpression(indexExpression), expression(expression) { }
StatementAssignmentKind StatementAssignment::getAssignmentKind() {
return assignmentKind;
}
string StatementAssignment::getName() { string StatementAssignment::getName() {
return name; return name;
} }
@@ -14,3 +18,7 @@ shared_ptr<Expression> StatementAssignment::getIndexExpression() {
shared_ptr<Expression> StatementAssignment::getExpression() { shared_ptr<Expression> StatementAssignment::getExpression() {
return expression; return expression;
} }
string StatementAssignment::getMemberName() {
return memberName;
}

View File

@@ -2,15 +2,25 @@
class Expression; class Expression;
enum class StatementAssignmentKind {
VARIABLE,
DATA,
BLOB
};
class StatementAssignment: public Statement { class StatementAssignment: public Statement {
private: private:
StatementAssignmentKind assignmentKind;
string name; string name;
shared_ptr<Expression> indexExpression; shared_ptr<Expression> indexExpression;
shared_ptr<Expression> expression; shared_ptr<Expression> expression;
string memberName;
public: public:
StatementAssignment(string name, shared_ptr<Expression> indexExpressio, shared_ptr<Expression> expression); StatementAssignment(string name, shared_ptr<Expression> indexExpressio, shared_ptr<Expression> expression);
StatementAssignmentKind getAssignmentKind();
string getName(); string getName();
shared_ptr<Expression> getIndexExpression(); shared_ptr<Expression> getIndexExpression();
shared_ptr<Expression> getExpression(); shared_ptr<Expression> getExpression();
string getMemberName();
}; };