@ -4,6 +4,76 @@
namespace molasses {
namespace unix_system {
struct syscall1 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 ) const {
int64_t ret ;
asm volatile ( " syscall " : " =a " ( ret ) : " 0 " ( syscall_id ) , " D " ( p1 ) : " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
struct syscall2 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 , int64_t p2 ) const {
int64_t ret ;
asm volatile ( " syscall " : " =a " ( ret ) : " 0 " ( syscall_id ) , " D " ( p1 ) , " S " ( p2 ) : " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
struct syscall3 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 , int64_t p2 , int64_t p3 ) const {
int64_t ret ;
asm volatile ( " syscall "
: " =a " ( ret )
: " 0 " ( syscall_id ) , " D " ( p1 ) , " S " ( p2 ) , " d " ( p3 )
: " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
struct syscall4 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 , int64_t p2 , int64_t p3 , int64_t p4 ) const {
int64_t ret ;
register long r10 asm ( " r10 " ) = p4 ;
asm volatile ( " syscall "
: " =a " ( ret )
: " 0 " ( syscall_id ) , " D " ( p1 ) , " S " ( p2 ) , " d " ( p3 ) , " r " ( r10 )
: " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
struct syscall5 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 , int64_t p2 , int64_t p3 , int64_t p4 , int64_t p5 ) const {
int64_t ret ;
register long r10 asm ( " r10 " ) = p4 ;
register long r8 asm ( " r8 " ) = p5 ;
asm volatile ( " syscall "
: " =a " ( ret )
: " 0 " ( syscall_id ) , " D " ( p1 ) , " S " ( p2 ) , " d " ( p3 ) , " r " ( r10 ) , " r " ( r8 )
: " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
struct syscall6 {
int64_t operator ( ) ( int64_t syscall_id , int64_t p1 , int64_t p2 , int64_t p3 , int64_t p4 , int64_t p5 , int64_t p6 ) const {
int64_t ret ;
register long r10 asm ( " r10 " ) = p4 ;
register long r8 asm ( " r8 " ) = p5 ;
register long r9 asm ( " r9 " ) = p6 ;
asm volatile ( " syscall "
: " =a " ( ret )
: " 0 " ( syscall_id ) , " D " ( p1 ) , " S " ( p2 ) , " d " ( p3 ) , " r " ( r10 ) , " r " ( r8 ) , " r " ( r9 )
: " rcx " , " r11 " , " memory " ) ;
return ret ;
}
} ;
}
std : : string marshal ( const std : : string & target ) {
std : : stringstream builder ;
bool is_first = true ;
@ -74,7 +144,15 @@ namespace molasses {
" addl %ebx, %eax \n " ,
" andl $0xFFFFFFFF, %eax \n " ,
" pushq %rax \n "
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_a = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_b = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int32_t > ( value_a ) or not std : : holds_alternative < int32_t > ( value_b ) ) {
// TODO: handle errors
}
current_stack . emplace ( get < int32_t > ( value_a ) + get < int32_t > ( value_b ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -87,7 +165,15 @@ namespace molasses {
" popq %rbx \n " ,
" addq %rbx, %rax \n " ,
" pushq %rax \n "
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_a = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_b = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int64_t > ( value_a ) or not std : : holds_alternative < int64_t > ( value_b ) ) {
// TODO: handle errors
}
current_stack . emplace ( get < int64_t > ( value_a ) + get < int64_t > ( value_b ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -102,7 +188,16 @@ namespace molasses {
" pushq %rax \n " ,
" pushq %rdx \n "
// TODO: this is actually unsigned division, so it needs improvements on negative numbers
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_a = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_b = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int64_t > ( value_a ) or not std : : holds_alternative < int64_t > ( value_b ) ) {
// TODO: handle errors
}
current_stack . emplace ( get < int64_t > ( value_a ) / get < int64_t > ( value_b ) ) ;
current_stack . emplace ( get < int64_t > ( value_a ) % get < int64_t > ( value_b ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -111,7 +206,14 @@ namespace molasses {
std : : vector < std : : string > ( { " u8 ptr " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < ptr_type > ( value ) & & not ( get < ptr_type > ( value ) . pointed - > name ( ) = = " u8 ptr " ) ) {
// TODO: handle errors
}
current_stack . emplace ( intptr_t ( get < ptr_type > ( value ) . ptr ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -120,12 +222,20 @@ namespace molasses {
std : : vector < std : : string > ( { " i32 " , " i32 " } ) ,
std : : vector < std : : string > ( { " i32 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rbx \n " ,
" imull %ebx, %eax \n " ,
" andl $0xFFFFFFFF, %eax \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rbx \n " ,
" imull %ebx, %eax \n " ,
" andl $0xFFFFFFFF, %eax \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_a = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_b = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int32_t > ( value_a ) or not std : : holds_alternative < int32_t > ( value_b ) ) {
// TODO: handle errors
}
current_stack . emplace ( get < int32_t > ( value_a ) * get < int32_t > ( value_b ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -134,12 +244,20 @@ namespace molasses {
std : : vector < std : : string > ( { " i32 " , " i32 " } ) ,
std : : vector < std : : string > ( { " i32 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rbx \n " ,
" subl %ebx, %eax \n " ,
" andl $0xFFFFFFFF, %eax \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rbx \n " ,
" subl %ebx, %eax \n " ,
" andl $0xFFFFFFFF, %eax \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_a = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_b = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int32_t > ( value_a ) or not std : : holds_alternative < int32_t > ( value_b ) ) {
// TODO: handle errors
}
current_stack . emplace ( get < int32_t > ( value_a ) - get < int32_t > ( value_b ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -148,10 +266,17 @@ namespace molasses {
std : : vector < std : : string > ( { " i32 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" movslq %eax, %rax \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" movslq %eax, %rax \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int32_t > ( value ) ) {
// TODO: handle errors
}
current_stack . emplace ( int64_t ( get < int32_t > ( value ) ) ) ;
}
)
) ;
@ -162,7 +287,13 @@ namespace molasses {
std : : vector < std : : string > ( { } ) ,
std : : vector < std : : string > ( {
" popq %rax \n "
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value = current_stack . top ( ) ; current_stack . pop ( ) ;
if ( not std : : holds_alternative < int64_t > ( value ) ) {
// TODO: handle errors
}
}
)
) ;
@ -176,7 +307,18 @@ namespace molasses {
" popq %rdi \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 )
) {
// TODO: handle errors
}
unix_system : : syscall1 { } ( get < int64_t > ( value_0 ) , get < int64_t > ( value_1 ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -185,12 +327,25 @@ namespace molasses {
std : : vector < std : : string > ( { " i64 " , " i64 " , " i64 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" syscall \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_2 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 ) or
not std : : holds_alternative < int64_t > ( value_2 )
) {
// TODO: handle errors
}
unix_system : : syscall2 { } ( get < int64_t > ( value_0 ) , get < int64_t > ( value_1 ) , get < int64_t > ( value_2 ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -199,13 +354,28 @@ namespace molasses {
std : : vector < std : : string > ( { " i64 " , " i64 " , " i64 " , " i64 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" syscall \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_2 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_3 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 ) or
not std : : holds_alternative < int64_t > ( value_2 ) or
not std : : holds_alternative < int64_t > ( value_3 )
) {
// TODO: handle errors
}
unix_system : : syscall3 { } ( get < int64_t > ( value_0 ) , get < int64_t > ( value_1 ) , get < int64_t > ( value_2 ) , get < int64_t > ( value_3 ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -214,14 +384,31 @@ namespace molasses {
std : : vector < std : : string > ( { " i64 " , " i64 " , " i64 " , " i64 " , " i64 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" syscall \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_2 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_3 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_4 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 ) or
not std : : holds_alternative < int64_t > ( value_2 ) or
not std : : holds_alternative < int64_t > ( value_3 ) or
not std : : holds_alternative < int64_t > ( value_4 )
) {
// TODO: handle errors
}
unix_system : : syscall4 { } ( get < int64_t > ( value_0 ) , get < int64_t > ( value_1 ) , get < int64_t > ( value_2 ) , get < int64_t > ( value_3 ) , get < int64_t > ( value_4 ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -230,15 +417,34 @@ namespace molasses {
std : : vector < std : : string > ( { " i64 " , " i64 " , " i64 " , " i64 " , " i64 " , " i64 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" popq %r8 \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" popq %r8 \n " ,
" syscall \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_2 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_3 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_4 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_5 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 ) or
not std : : holds_alternative < int64_t > ( value_2 ) or
not std : : holds_alternative < int64_t > ( value_3 ) or
not std : : holds_alternative < int64_t > ( value_4 ) or
not std : : holds_alternative < int64_t > ( value_5 )
) {
// TODO: handle errors
}
unix_system : : syscall5 { } ( get < int64_t > ( value_0 ) , get < int64_t > ( value_1 ) , get < int64_t > ( value_2 ) , get < int64_t > ( value_3 ) , get < int64_t > ( value_4 ) , get < int64_t > ( value_5 ) ) ;
}
)
) ;
ctx . operations . emplace_back (
@ -247,16 +453,46 @@ namespace molasses {
std : : vector < std : : string > ( { " i64 " , " i64 " , " i64 " , " i64 " , " i64 " , " i64 " , " i64 " } ) ,
std : : vector < std : : string > ( { " i64 " } ) ,
std : : vector < std : : string > ( {
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" popq %r8 \n " ,
" popq %r9 \n " ,
" syscall \n " ,
" pushq %rax \n "
} )
" popq %rax \n " ,
" popq %rdi \n " ,
" popq %rsi \n " ,
" popq %rdx \n " ,
" popq %r10 \n " ,
" popq %r8 \n " ,
" popq %r9 \n " ,
" syscall \n " ,
" pushq %rax \n "
} ) ,
[ ] ( const generate_context & , interpreter_stack & current_stack ) {
auto value_0 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_1 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_2 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_3 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_4 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_5 = current_stack . top ( ) ; current_stack . pop ( ) ;
auto value_6 = current_stack . top ( ) ; current_stack . pop ( ) ;
if (
not std : : holds_alternative < int64_t > ( value_0 ) or
not std : : holds_alternative < int64_t > ( value_1 ) or
not std : : holds_alternative < int64_t > ( value_2 ) or
not std : : holds_alternative < int64_t > ( value_3 ) or
not std : : holds_alternative < int64_t > ( value_4 ) or
not std : : holds_alternative < int64_t > ( value_5 ) or
not std : : holds_alternative < int64_t > ( value_6 )
) {
// TODO: handle errors
}
unix_system : : syscall6 { } (
get < int64_t > ( value_0 ) ,
get < int64_t > ( value_1 ) ,
get < int64_t > ( value_2 ) ,
get < int64_t > ( value_3 ) ,
get < int64_t > ( value_4 ) ,
get < int64_t > ( value_5 ) ,
get < int64_t > ( value_6 )
) ;
}
)
) ;