Syscall* ASTNodes and LLVM IR generation for x86
Inline assembly for the win!
This commit is contained in:
parent
7522858897
commit
085677bc2b
@ -47,6 +47,8 @@ add_executable(
|
||||
src/AST/NumberNode.h
|
||||
src/AST/SumNode.cpp
|
||||
src/AST/SumNode.h
|
||||
src/AST/SyscallNode.cpp
|
||||
src/AST/SyscallNode.h
|
||||
src/utils.cpp
|
||||
src/utils.h
|
||||
src/Parser.cpp
|
||||
|
258
src/AST/SyscallNode.cpp
Normal file
258
src/AST/SyscallNode.cpp
Normal file
@ -0,0 +1,258 @@
|
||||
#include "SyscallNode.h"
|
||||
#include "../Arguments.h"
|
||||
#include "../Error.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
|
||||
Syscall0Node::Syscall0Node(int syscall_number) : sys_num(syscall_number), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall0Node::~Syscall0Node()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall1Node::Syscall1Node(int syscall_number, std::shared_ptr<ASTNode> arg1)
|
||||
: sys_num(syscall_number), arg1(arg1), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall1Node::~Syscall1Node()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall2Node::Syscall2Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2)
|
||||
: sys_num(syscall_number), arg1(arg1), arg2(arg2), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall2Node::~Syscall2Node()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall3Node::Syscall3Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3)
|
||||
: sys_num(syscall_number), arg1(arg1), arg2(arg2), arg3(arg3), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall3Node::~Syscall3Node()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall4Node::Syscall4Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3, std::shared_ptr<ASTNode> arg4)
|
||||
: sys_num(syscall_number), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall4Node::~Syscall4Node()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall5Node::Syscall5Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3, std::shared_ptr<ASTNode> arg4, std::shared_ptr<ASTNode> arg5)
|
||||
: sys_num(syscall_number), arg1(arg1), arg2(arg2), arg3(arg3), arg4(arg4), arg5(arg5), ExprNode()
|
||||
{
|
||||
}
|
||||
|
||||
Syscall5Node::~Syscall5Node()
|
||||
{
|
||||
}
|
||||
|
||||
llvm::Value* Syscall0Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value* Syscall1Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax},{rdi}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
arg1->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i,{ebx}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80),
|
||||
arg1->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value* Syscall2Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax},{rdi},{rsi}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
arg1->codegen(generator), arg2->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i,{ebx},{ecx}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80),
|
||||
arg1->codegen(generator), arg2->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value* Syscall3Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax},{rdi},{rsi},{rcx}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i,{ebx},{ecx},{edx}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value* Syscall4Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax},{rdi},{rsi},{rdx},{rcx}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator), arg4->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i,{ebx},{ecx},{edx},{esi}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator), arg4->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Value* Syscall5Node::codegen(IRBuilder* generator)
|
||||
{
|
||||
switch (Arguments::TargetTriple.getArch())
|
||||
{
|
||||
case llvm::Triple::x86_64: {
|
||||
auto i64Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt64Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i64Type, "syscall", "=r,{rax},{rdi},{rsi},{rdx},{rcx},{r8}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator), arg4->codegen(generator),
|
||||
arg5->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::x86: {
|
||||
auto i32Type =
|
||||
llvm::FunctionType::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), false);
|
||||
auto inlineAsm = llvm::InlineAsm::get(i32Type, "int $2", "=r,{eax},i,{ebx},{ecx},{edx},{esi},{edi}", true);
|
||||
return generator->getBuilder()->CreateCall(
|
||||
inlineAsm,
|
||||
{llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), sys_num),
|
||||
llvm::ConstantInt::get(llvm::IntegerType::getInt32Ty(generator->getBuilder()->getContext()), 0x80),
|
||||
arg1->codegen(generator), arg2->codegen(generator), arg3->codegen(generator), arg4->codegen(generator),
|
||||
arg5->codegen(generator)});
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Error::throw_error_without_location(
|
||||
std::string("Unsupported arch for syscalls: ") +
|
||||
Arguments::TargetTriple.getArchName(Arguments::TargetTriple.getArch()).str());
|
||||
break;
|
||||
}
|
||||
}
|
86
src/AST/SyscallNode.h
Normal file
86
src/AST/SyscallNode.h
Normal file
@ -0,0 +1,86 @@
|
||||
#pragma once
|
||||
#include "ExprNode.h"
|
||||
|
||||
class Syscall0Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
|
||||
public:
|
||||
Syscall0Node(int syscall_number);
|
||||
~Syscall0Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
||||
|
||||
class Syscall1Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
std::shared_ptr<ASTNode> arg1;
|
||||
|
||||
public:
|
||||
Syscall1Node(int syscall_number, std::shared_ptr<ASTNode> arg1);
|
||||
~Syscall1Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
||||
|
||||
class Syscall2Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
std::shared_ptr<ASTNode> arg1;
|
||||
std::shared_ptr<ASTNode> arg2;
|
||||
|
||||
public:
|
||||
Syscall2Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2);
|
||||
~Syscall2Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
||||
|
||||
class Syscall3Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
std::shared_ptr<ASTNode> arg1;
|
||||
std::shared_ptr<ASTNode> arg2;
|
||||
std::shared_ptr<ASTNode> arg3;
|
||||
|
||||
public:
|
||||
Syscall3Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3);
|
||||
~Syscall3Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
||||
|
||||
class Syscall4Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
std::shared_ptr<ASTNode> arg1;
|
||||
std::shared_ptr<ASTNode> arg2;
|
||||
std::shared_ptr<ASTNode> arg3;
|
||||
std::shared_ptr<ASTNode> arg4;
|
||||
|
||||
public:
|
||||
Syscall4Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3, std::shared_ptr<ASTNode> arg4);
|
||||
~Syscall4Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
||||
|
||||
class Syscall5Node final : public ExprNode
|
||||
{
|
||||
int sys_num;
|
||||
std::shared_ptr<ASTNode> arg1;
|
||||
std::shared_ptr<ASTNode> arg2;
|
||||
std::shared_ptr<ASTNode> arg3;
|
||||
std::shared_ptr<ASTNode> arg4;
|
||||
std::shared_ptr<ASTNode> arg5;
|
||||
|
||||
public:
|
||||
Syscall5Node(int syscall_number, std::shared_ptr<ASTNode> arg1, std::shared_ptr<ASTNode> arg2,
|
||||
std::shared_ptr<ASTNode> arg3, std::shared_ptr<ASTNode> arg4, std::shared_ptr<ASTNode> arg5);
|
||||
~Syscall5Node();
|
||||
|
||||
llvm::Value* codegen(IRBuilder* generator) override;
|
||||
};
|
Loading…
Reference in New Issue
Block a user