https://github.com/wizardpisces/js-ziju
Compile javascript to LLVM IR, x86 assembly and self interpreting
https://github.com/wizardpisces/js-ziju
assembly ast compiler interpreter llvm machine
Last synced: about 2 months ago
JSON representation
Compile javascript to LLVM IR, x86 assembly and self interpreting
- Host: GitHub
- URL: https://github.com/wizardpisces/js-ziju
- Owner: wizardpisces
- License: mit
- Created: 2020-12-23T08:55:38.000Z (over 4 years ago)
- Default Branch: main
- Last Pushed: 2021-09-16T03:27:39.000Z (over 3 years ago)
- Last Synced: 2024-03-18T13:01:37.353Z (about 1 year ago)
- Topics: assembly, ast, compiler, interpreter, llvm, machine
- Language: TypeScript
- Homepage:
- Size: 328 KB
- Stars: 163
- Watchers: 3
- Forks: 10
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Project Description
A compiler for javascript targeting LLVM IR, x86 assembly , self interpreting etc...## A learning project for you to understand below list
* How a compiler work and how to build one
* How does code run from source
* How to compile code to Assembly or LLVM IR## Examples
### Interpret
```ts
import {
Interpreter
} from './src'let code = `
console.log('=== MemberExpression evaluated =========');
function fn(){
console.log('=== FunctionDeclaration evaluated =====')
}
fn()
`new Interpreter(code).interpret()
/* output:
* === MemberExpression evaluated =========
* === FunctionDeclaration evaluated =====
*/
```
### X86 MASM Assembly```js
import {Assembler} from './src'let kernalCode = `
function printChar($$c){
console.log(1,$$c,1)
}function printHelper(n) {
if(n>9){
printHelper(n / 10)
}
// 48 is the ASCII code for '0'
printChar(48 + n % 10);
}function print(n){
printHelper(n)
printChar(10); // 换行
}`let code = `
function main(){
print(231)
print(4)
}`let result = new Assembler(kernal+code).compile()
```
result.assembly
```assembly
.global _main.text
printChar:
PUSH RBP
MOV RBP, RSPPUSH 1
MOV RAX, RBP
ADD RAX, 16 # $$c
PUSH RAX
PUSH 1
POP RDX
POP RSI
POP RDI
MOV RAX, 33554436
SYSCALL
PUSH RAXPOP RAX
POP RBPRET
printHelper:
PUSH RBP
MOV RBP, RSP# If
# >
PUSH [RBP + 16] # n
PUSH 9
POP RAX
CMP [RSP], RAX
MOV RAX, 0
MOV DWORD PTR [RSP], 1
CMOVA RAX, [RSP]
MOV [RSP], RAX
# End >POP RAX
TEST RAX, RAX
JZ .else_branch1# If then
# DIV
PUSH [RBP + 16] # n
PUSH 10
POP RAX
XCHG [RSP], RAX
XOR RDX, RDX
DIV QWORD PTR [RSP]
MOV [RSP], RAX
CALL printHelper
MOV [RSP], RAXJMP .after_else_branch1
# If else
.else_branch1:
PUSH 0 # Null else branch
.after_else_branch1:
# End if
POP RAX # Ignore non-final expression
# ADD
PUSH 48
# DIV
PUSH [RBP + 16] # n
PUSH 10
POP RAX
XCHG [RSP], RAX
XOR RDX, RDX
DIV QWORD PTR [RSP]
MOV [RSP], RDX
POP RAX
ADD [RSP], RAX
# End ADD
CALL printChar
MOV [RSP], RAXPOP RAX
POP RBPRET
print:
PUSH RBP
MOV RBP, RSPPUSH [RBP + 16] # n
CALL printHelper
MOV [RSP], RAXPOP RAX # Ignore non-final expression
PUSH 10
CALL printChar
MOV [RSP], RAXPOP RAX
POP RBPRET
main:
PUSH RBP
MOV RBP, RSPPUSH 231
CALL print
MOV [RSP], RAXPOP RAX # Ignore non-final expression
PUSH 4
CALL print
MOV [RSP], RAXPOP RAX
POP RBPRET
_main:
CALL main
MOV RDI, RAX
MOV RAX, 33554433
SYSCALL```
### LLVM
```js
import {Assembler} from './src'let kernalCode = `
function printChar($$c){
console.log(1,$$c,1)
}function printHelper(n) {
if(n>9){
printHelper(n / 10)
}
// 48 is the ASCII code for '0'
printChar(48 + n % 10);
}function print(n){
printHelper(n)
printChar(10); // 换行
}`let code = `
function main(){
print(311)
// print(4)
}`let result = new Assembler(kernal+code).llvmCompile()
```
result.assembly
```llvm
define i64 @printChar(i64 %$$c) {
%sym5 = add i64 1, 0
%sym7 = add i64 %$$c, 0
%sym6 = alloca i64, align 4
store i64 %sym7, i64* %sym6, align 4
%sym8 = add i64 1, 0
%sym9 = add i64 33554436, 0
%sym4 = call i64 asm sideeffect "syscall", "=r,{rax},{rdi},{rsi},{rdx},~{dirflag},~{fpsr},~{flags}" (i64 %sym9, i64 %sym5, i64* %sym6, i64 %sym8)
}define i64 @printHelper(i64 %n) {
%ifresult8 = alloca i64, align 4
%sym9 = add i64 %n, 0
%sym10 = add i64 9, 0
%sym7 = icmp sgt i64 %sym9, %sym10
br i1 %sym7, label %iftrue11, label %iffalse12
iftrue11:
%sym15 = add i64 %n, 0
%sym16 = add i64 10, 0
%sym14 = udiv i64 %sym15, %sym16
%sym13 = call i64 @printHelper(i64 %sym14)
store i64 %sym13, i64* %ifresult8, align 4
br label %ifend17
iffalse12:
br label %ifend17
ifend17:
%sym6 = load i64, i64* %ifresult8, align 4
%sym19 = add i64 48, 0
%sym21 = add i64 %n, 0
%sym22 = add i64 10, 0
%sym20 = urem i64 %sym21, %sym22
%sym18 = add i64 %sym19, %sym20
%sym6 = call i64 @printChar(i64 %sym18)
}define i64 @print(i64 %n) {
%sym9 = add i64 %n, 0
%sym8 = call i64 @printHelper(i64 %sym9)
%sym10 = add i64 10, 0
%sym8 = call i64 @printChar(i64 %sym10)
}define i64 @main() {
%sym10 = add i64 311, 0
%sym9 = call i64 @print(i64 %sym10)
}
```### How to test (support node>=12)
```
npm install
```
**Prepare "gcc" and "llc" enviroment or else only interpret.spec.ts could pass the test**
```
npm run test
```## Detail
Further info could reference test cases
## Refenrece
### Project
* [build a sass compiler from scratch](https://github.com/wizardpisces/tiny-sass-compiler)
### LLVM
* Manual
* [LLVM](https://llvm.org/docs/LangRef.html)
### NASM
* Tutorial
* [NASM](https://cs.lmu.edu/~ray/notes/nasmtutorial/)
### MASM X86 Assembly
* Manual
* [X86-assembly-instructions](https://www.aldeid.com/wiki/X86-assembly/Instructions/mov)
* Tutorial
* [NASM](https://cs.lmu.edu/~ray/notes/nasmtutorial/)
* Article
* [introduction-to-x64-assembly](https://software.intel.com/content/www/us/en/develop/articles/introduction-to-x64-assembly.html)
### Common
* Project
* [Estree](https://github.com/estree/estree/blob/master/es2015.md)
* Tools
* [online llvm compiler](http://ellcc.org/demo/index.cgi)
* [compiler explorer](https://godbolt.org/)
* [ast explorer](https://astexplorer.net/#/gist/244e2fb4da940df52bf0f4b94277db44/e79aff44611020b22cfd9708f3a99ce09b7d67a8)
* Article
* [compiler-basics-lisp-to-assembly](https://notes.eatonphil.com/compiler-basics-lisp-to-assembly.html)
* [vm-arch](https://www.codeproject.com/Articles/461052/Stack-Based-vs-Register-Based-Virtual-Machine-Arch)
* [making-system-calls-from-assembly-in-mac-os-x](https://filippo.io/making-system-calls-from-assembly-in-mac-os-x/)
* [ir-is-better-than-assembly](https://idea.popcount.org/2013-07-24-ir-is-better-than-assembly/)
* [编程达到一个高的境界就是自制脚本语言](https://cloud.tencent.com/developer/news/305527)