Generate code for custom type

This commit is contained in:
Rafał Grodziński
2025-08-05 11:16:50 +09:00
parent dc8d10c81c
commit b6c2ff3983
8 changed files with 113 additions and 22 deletions

View File

@@ -1,8 +1,8 @@
User type
User pack
;
main fun -> u32
//user User
user User <- 0
ret 0
;

View File

@@ -16,6 +16,7 @@
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementRawFunction.h"
#include "Parser/Statement/StatementType.h"
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
@@ -68,6 +69,9 @@ void ModuleBuilder::buildStatement(shared_ptr<Statement> statement) {
case StatementKind::RAW_FUNCTION:
buildRawFunction(dynamic_pointer_cast<StatementRawFunction>(statement));
break;
case StatementKind::TYPE:
buildType(dynamic_pointer_cast<StatementType>(statement));
break;
case StatementKind::VARIABLE:
buildVarDeclaration(dynamic_pointer_cast<StatementVariable>(statement));
break;
@@ -160,6 +164,14 @@ void ModuleBuilder::buildRawFunction(shared_ptr<StatementRawFunction> statement)
return;
}
void ModuleBuilder::buildType(shared_ptr<StatementType> statement) {
llvm::StructType *structType = llvm::StructType::create(*context, statement->getIdentifier());
vector<llvm::Type *> elements;
structType->setBody(elements, false);
if (!setStruct(statement->getIdentifier(), structType))
return;
}
void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement) {
if (statement->getValueType()->getKind() == ValueTypeKind::DATA) {
vector<llvm::Value *> values = valuesForExpression(statement->getExpression());
@@ -177,6 +189,11 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement)
builder->CreateStore(values[i], elementPtr);
}
} else if (statement->getValueType()->getKind() == ValueTypeKind::TYPE) {
llvm::StructType *type = (llvm::StructType *)typeForValueType(statement->getValueType(), 0);
llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, statement->getName());
if (!setAlloca(statement->getName(), alloca))
return;
} else {
llvm::Value *value = valueForExpression(statement->getExpression());
if (value == nullptr)
@@ -671,6 +688,29 @@ 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));
return false;
}
scopes.top().structTypeMap[name] = structType;
return true;
}
llvm::StructType *ModuleBuilder::getStructType(string name) {
stack<Scope> scopes = this->scopes;
while (!scopes.empty()) {
llvm::StructType *structType = scopes.top().structTypeMap[name];
if (structType != nullptr)
return structType;
scopes.pop();
}
return nullptr;
}
llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int count) {
if (valueType == nullptr) {
markError(0, 0, "Missing type");
@@ -699,6 +739,8 @@ llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int
count = valueType->getValueArg();
return llvm::ArrayType::get(typeForValueType(valueType->getSubType(), count), count);
}
case ValueTypeKind::TYPE:
return getStructType(valueType->getTypeName());
}
}

View File

@@ -29,6 +29,7 @@ enum class ExpressionBinaryOperation;
class Statement;
class StatementFunction;
class StatementRawFunction;
class StatementType;
class StatementVariable;
class StatementAssignment;
class StatementReturn;
@@ -43,6 +44,7 @@ typedef struct {
map<string, llvm::AllocaInst*> allocaMap;
map<string, llvm::Function*> funMap;
map<string, llvm::InlineAsm*> rawFunMap;
map<string, llvm::StructType*> structTypeMap;
} Scope;
class ModuleBuilder {
@@ -69,6 +71,7 @@ private:
void buildStatement(shared_ptr<Statement> statement);
void buildFunction(shared_ptr<StatementFunction> statement);
void buildRawFunction(shared_ptr<StatementRawFunction> statement);
void buildType(shared_ptr<StatementType> statement);
void buildVarDeclaration(shared_ptr<StatementVariable> statement);
void buildAssignment(shared_ptr<StatementAssignment> statement);
void buildBlock(shared_ptr<StatementBlock> statement);
@@ -101,6 +104,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);
llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0);
void markError(int line, int column, string message);

View File

@@ -12,6 +12,7 @@
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementRawFunction.h"
#include "Parser/Statement/StatementType.h"
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
@@ -223,6 +224,8 @@ string Logger::toString(shared_ptr<ValueType> valueType) {
return "R32";
case ValueTypeKind::DATA:
return "[]";
case ValueTypeKind::TYPE:
return format("TYPE({})", valueType->getTypeName());
}
}
@@ -236,6 +239,8 @@ string Logger::toString(shared_ptr<Statement> statement) {
return toString(dynamic_pointer_cast<StatementFunction>(statement));
case StatementKind::RAW_FUNCTION:
return toString(dynamic_pointer_cast<StatementRawFunction>(statement));
case StatementKind::TYPE:
return toString(dynamic_pointer_cast<StatementType>(statement));
case StatementKind::BLOCK:
return toString(dynamic_pointer_cast<StatementBlock>(statement));
case StatementKind::ASSIGNMENT:
@@ -296,6 +301,14 @@ string Logger::toString(shared_ptr<StatementRawFunction> statement) {
return text;
}
string Logger::toString(shared_ptr<StatementType> statement) {
string text;
text += format("TYPE(\"{}\"):\n", statement->getIdentifier());
return text;
}
string Logger::toString(shared_ptr<StatementBlock> statement) {
string text;

View File

@@ -12,6 +12,7 @@ class StatementMetaExternFunction;
class StatementVariable;
class StatementFunction;
class StatementRawFunction;
class StatementType;
class StatementBlock;
class StatementAssignment;
class StatementReturn;
@@ -44,6 +45,7 @@ private:
static string toString(shared_ptr<StatementVariable> statement);
static string toString(shared_ptr<StatementFunction> statement);
static string toString(shared_ptr<StatementRawFunction> statement);
static string toString(shared_ptr<StatementType> statement);
static string toString(shared_ptr<StatementBlock> statement);
static string toString(shared_ptr<StatementAssignment> statement);
static string toString(shared_ptr<StatementReturn> statement);

View File

@@ -503,31 +503,38 @@ shared_ptr<Statement> Parser::matchStatementType() {
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::tokenParsee(TokenKind::TYPE, true, false)
},
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
{}
)
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
identifier = resultsGroup.getResults().at(0).getToken()->getLexme();
for (int i=1; i<resultsGroup.getResults().size(); i+=2) {
pair<string, shared_ptr<ValueType>> arg;
arg.first = resultsGroup.getResults().at(i).getToken()->getLexme();
arg.second = resultsGroup.getResults().at(i+1).getValueType();
variables.push_back(arg);
}
/*for (int i=1; i<resultsGroup.getResults().size(); i+=2) {
pair<string, shared_ptr<ValueType>> arg;
arg.first = resultsGroup.getResults().at(i).getToken()->getLexme();
arg.second = resultsGroup.getResults().at(i+1).getValueType();
variables.push_back(arg);
}*/
break;
case ParseeResultsGroupKind::NO_MATCH:
case ParseeResultsGroupKind::FAILURE:
return nullptr;
break;
}
// consume new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
markError(TokenKind::NEW_LINE, {});
return nullptr;
}
// closing semicolon
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) {
markError(TokenKind::SEMICOLON, {});
return nullptr;
}
return make_shared<StatementType>(identifier, variables);
}

View File

@@ -10,27 +10,38 @@ shared_ptr<ValueType> ValueType::S8 = make_shared<ValueType>(ValueTypeKind::S8,
shared_ptr<ValueType> ValueType::S32 = make_shared<ValueType>(ValueTypeKind::S32, nullptr, 0);
shared_ptr<ValueType> ValueType::R32 = make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
ValueType::ValueType() { }
ValueType::ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg):
kind(kind), subType(subType), valueArg(valueArg) { }
shared_ptr<ValueType> ValueType::type(string typeName) {
shared_ptr<ValueType> valueType = make_shared<ValueType>();
valueType->kind = ValueTypeKind::TYPE;
valueType->typeName = typeName;
return valueType;
}
shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg) {
switch (token->getKind()) {
case TokenKind::TYPE: {
string lexme = token->getLexme();
if (lexme.compare("bool") == 0)
return make_shared<ValueType>(ValueTypeKind::BOOL, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
else if (lexme.compare("u8") == 0)
return make_shared<ValueType>(ValueTypeKind::U8, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::U8, nullptr, 0);
else if (lexme.compare("u32") == 0)
return make_shared<ValueType>(ValueTypeKind::U32, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::U32, nullptr, 0);
else if (lexme.compare("s8") == 0)
return make_shared<ValueType>(ValueTypeKind::S8, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::S8, nullptr, 0);
else if (lexme.compare("s32") == 0)
return make_shared<ValueType>(ValueTypeKind::S32, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::S32, nullptr, 0);
else if (lexme.compare("r32") == 0)
return make_shared<ValueType>(ValueTypeKind::R32, subType, valueArg);
return make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
else if (lexme.compare("data") == 0)
return make_shared<ValueType>(ValueTypeKind::DATA, subType, valueArg);
else if (lexme.compare("type") != 0)
return ValueType::type(token->getLexme());
else
return nullptr;
}
@@ -59,4 +70,8 @@ shared_ptr<ValueType> ValueType::getSubType() {
int ValueType::getValueArg() {
return valueArg;
}
string ValueType::getTypeName() {
return typeName;
}

View File

@@ -2,6 +2,7 @@
#define VALUE_TYPE_H
#include <optional>
#include <string>
class Token;
@@ -15,7 +16,8 @@ enum class ValueTypeKind {
S8,
S32,
R32,
DATA
DATA,
TYPE
};
class ValueType {
@@ -23,6 +25,7 @@ private:
ValueTypeKind kind;
shared_ptr<ValueType> subType;
int valueArg;
string typeName;
public:
static shared_ptr<ValueType> NONE;
@@ -34,10 +37,13 @@ public:
static shared_ptr<ValueType> R32;
static shared_ptr<ValueType> valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg);
ValueType();
ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg);
static shared_ptr<ValueType> type(string typeName);
ValueTypeKind getKind();
shared_ptr<ValueType> getSubType();
int getValueArg();
string getTypeName();
};
#endif