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
us User
us<- 5
ret 0
;

View File

@@ -168,15 +168,17 @@ void ModuleBuilder::buildBlob(shared_ptr<StatementBlob> statement) {
llvm::StructType *structType = llvm::StructType::create(*context, statement->getIdentifier());
// Generate types for body
vector<string> memberNames;
vector<llvm::Type *> types;
for (pair<string, shared_ptr<ValueType>> &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<StatementAssignment> 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<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;
}
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<string> 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<Scope> 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<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) {
if (valueType == nullptr) {
markError(0, 0, "Missing type");

View File

@@ -45,6 +45,7 @@ typedef struct {
map<string, llvm::Function*> funMap;
map<string, llvm::InlineAsm*> rawFunMap;
map<string, llvm::StructType*> structTypeMap;
map<string, vector<string>> 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<string> memberNames);
llvm::StructType *getStructType(string structName);
optional<int> getMemberIndex(string structName, string memberName);
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):
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<Expression> StatementAssignment::getIndexExpression() {
shared_ptr<Expression> StatementAssignment::getExpression() {
return expression;
}
string StatementAssignment::getMemberName() {
return memberName;
}

View File

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