Build raw function

This commit is contained in:
Rafał Grodziński
2025-07-13 15:06:52 +09:00
parent 26c566f4f6
commit 228dd80423
4 changed files with 35 additions and 20 deletions

View File

@@ -25,8 +25,10 @@ i u32 <- 0, rep text[i] != 0:
;*/ ;*/
rawAdd raw rawAdd raw
mov eax, 5 //push rbx
mov ebx, 42 mov ebx, 5
//pop rbx
mov eax, 42
add eax, ebx add eax, ebx
; ;

View File

@@ -131,8 +131,11 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> state
} }
void ModuleBuilder::buildRawFunction(shared_ptr<StatementRawFunction> statement) { void ModuleBuilder::buildRawFunction(shared_ptr<StatementRawFunction> statement) {
llvm::FunctionType *funType = llvm::FunctionType::get(llvm::Type::getVoidTy(*context), nullptr, false); // get argument types
llvm::InlineAsm *rawFun = llvm::InlineAsm::get(funType, statement->getRawSource(), "", false, false, llvm::InlineAsm::AsmDialect::AD_Intel); vector<llvm::Type *> types;
llvm::FunctionType *funType = llvm::FunctionType::get(llvm::Type::getVoidTy(*context), types, false);
llvm::InlineAsm *rawFun = llvm::InlineAsm::get(funType, statement->getRawSource(), "~{ebx}", false, false, llvm::InlineAsm::AsmDialect::AD_Intel);
if (!setRawFun(statement->getName(), rawFun)) if (!setRawFun(statement->getName(), rawFun))
return; return;
@@ -508,15 +511,24 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVariable> expressio
llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) { llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) {
llvm::Function *fun = getFun(expression->getName()); llvm::Function *fun = getFun(expression->getName());
if (fun == nullptr) if (fun != nullptr) {
return nullptr; llvm::FunctionType *funType = fun->getFunctionType();
llvm::FunctionType *funType = fun->getFunctionType(); vector<llvm::Value*> argValues;
vector<llvm::Value*> argValues; for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) {
for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) { llvm::Value *argValue = valueForExpression(argumentExpression);
llvm::Value *argValue = valueForExpression(argumentExpression); argValues.push_back(argValue);
argValues.push_back(argValue); }
return builder->CreateCall(funType, fun, llvm::ArrayRef(argValues));
} }
return builder->CreateCall(funType, fun, llvm::ArrayRef(argValues));
llvm::InlineAsm *rawFun = getRawFun(expression->getName());
if (rawFun != nullptr) {
vector<llvm::Value *>argValues;
return builder->CreateCall(rawFun, llvm::ArrayRef(argValues));
}
markError(0, 0, format("Function \"{}\" not defined in scope", expression->getName()));
return nullptr;
} }
bool ModuleBuilder::setAlloca(string name, llvm::AllocaInst *alloca) { bool ModuleBuilder::setAlloca(string name, llvm::AllocaInst *alloca) {
@@ -563,11 +575,10 @@ llvm::Function* ModuleBuilder::getFun(string name) {
scopes.pop(); scopes.pop();
} }
markError(0, 0, format("Function \"{}\" not defined in scope", name));
return nullptr; return nullptr;
} }
bool ModuleBuilder::setRawFun(string name, llvm::Value *rawFun) { bool ModuleBuilder::setRawFun(string name, llvm::InlineAsm *rawFun) {
if (scopes.top().rawFunMap[name] != nullptr) { if (scopes.top().rawFunMap[name] != nullptr) {
markError(0, 0, format("Raw function \"{}\" already defined in scope", name)); markError(0, 0, format("Raw function \"{}\" already defined in scope", name));
return false; return false;
@@ -577,17 +588,16 @@ bool ModuleBuilder::setRawFun(string name, llvm::Value *rawFun) {
return true; return true;
} }
llvm::Value *ModuleBuilder::getRawFun(string name) { llvm::InlineAsm *ModuleBuilder::getRawFun(string name) {
stack<Scope> scopes = this->scopes; stack<Scope> scopes = this->scopes;
while (!scopes.empty()) { while (!scopes.empty()) {
llvm::Value *rawFun = scopes.top().rawFunMap[name]; llvm::InlineAsm *rawFun = scopes.top().rawFunMap[name];
if (rawFun != nullptr) if (rawFun != nullptr)
return rawFun; return rawFun;
scopes.pop(); scopes.pop();
} }
markError(0, 0, format("Raw function \"{}\" not defined in scope", name));
return nullptr; return nullptr;
} }

View File

@@ -41,7 +41,7 @@ using namespace std;
typedef struct { typedef struct {
map<string, llvm::AllocaInst*> allocaMap; map<string, llvm::AllocaInst*> allocaMap;
map<string, llvm::Function*> funMap; map<string, llvm::Function*> funMap;
map<string, llvm::Value*> rawFunMap; map<string, llvm::InlineAsm*> rawFunMap;
} Scope; } Scope;
class ModuleBuilder { class ModuleBuilder {
@@ -92,8 +92,8 @@ private:
bool setFun(string name, llvm::Function *fun); bool setFun(string name, llvm::Function *fun);
llvm::Function *getFun(string name); llvm::Function *getFun(string name);
bool setRawFun(string name, llvm::Value *rawFun); bool setRawFun(string name, llvm::InlineAsm *rawFun);
llvm::Value *getRawFun(string name); llvm::InlineAsm *getRawFun(string name);
llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0); llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0);

View File

@@ -257,6 +257,9 @@ shared_ptr<Statement> Parser::matchStatementRawFunction() {
if (!rawSource.empty()) if (!rawSource.empty())
rawSource += "\n"; rawSource += "\n";
rawSource += tokens.at(currentIndex++)->getLexme(); rawSource += tokens.at(currentIndex++)->getLexme();
// Consume optional new line (for example because of a comment)
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
} }
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) { if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) {