SysyPlus Compiler编译器

说明

Posted by MetaNetworks on March 17, 2021
本页面总访问量

SysyPlus Language For MetaNetworks

使用LLVM框架的SysyPlus语言编译器

当前编译状态:build status

LLVM框架语言:LLVM 12.0.0

工具库依赖:libBoost、LLVM、glib

界面依赖:gtkmm3

编译环境:cmake 3.13 + Deepin 20.1 Beta

编译时若出错请注意LLVM版本号

背景

SysyPlus编译器偏向于生成网络方面的执行代码,让小白开发者也可以做一个简单、易用、高性能、安全的http服务器。后期根据开发进度开发其他功能。

众所周知:c的http晦涩难学,导包过于繁琐。但性能最好,python的http简单,但是是解释型语言,源码直接暴露,java的http也有学习成本, 且针对简单的http服务使用java这种复杂通用性语言有剩余空间,杀鸡焉用牛刀。

SysyPlus编译器致力于打造一个简单语法的http服务器,上手即用语法简单,不用导任何包,不用管依赖问题, 生成的产物为编译好的可执行文件,文件小,安全,且能利用python不能使用的多核cpu线程优势。

效果图

以用程序自带访问一次HTTP为例

  • IDE GUI可直接进行代码静态分析(变量不存在,函数重复定义等)
  • IDE GUI拥有丰富的代码提示功能
  • 编译或执行SysyPlus代码
  • 当然你也可以当一个文本编辑器

编译选项

  • CGUI
    • 开启图形界面编译,生成带GUI的编译器
  • DEBUG_FLAG
    • 开启词法、语法的调试模式

目前支持程度

  • 函数定义
    • 参数
  • 二元表达式
    • &&、  
    • +、-、*、/、%、!=
  • 函数调用
    • 传参
      • 基础类型、数组、多维数组传参
  • 条件分支关键字
    • if
  • 循环关键字(c++ -> sysyplus)
    • for -> lp
    • While -> whl
    • break -> out
      • continue -> cont
  • 函数返回 return -> ret
    • 保持单入单出特性
  • 全局、局部变量
  • 数组
    • 全局、局部数组/多维数组
    • 数组定义时初始化
  • 字符串
    • 局部、全局声明、传值
  • 语言特色
    • sleep(s) 休眠
    • echo(str) 输出
    • now(null) 获取当前秒数
  • web功能
    • 创建socket
    • 连接url
    • 发送GET请求
    • 发送POST请求(正在开发中)
  • 代码插桩/优化功能
    • 函数执行时间分析
    • 递归函数转非递归(正在开发中)
  • 生成AST语法树
  • 生成对应系统架构的目标代码
  • …(比较懒,不想写)

一段SySyPlus源文件

  • 无需导包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int main(){
    sleep(1);
    echo('init web framework', '123', '345');
    int socketId = getSocket();
    echo('socket id is',socketId);
    str url = 'file.ketanetwork.cc';
    str port = '443';
    echo('url is:',url,' port is:',port);
    int state = connectSocket(socketId,url,port);
    state = isSocketConnected(socketId);
    if (state == 0){
        echo('socket connected');
        echo('sending get request');
        str response = getRequest(socketId,url,'/');
        echo('response is:');
        echo(response);
    }
    closeSocket(socketId);
    ret 0;
}
  • 编译输出
    • 可直接运行 ```shell ➜ Desktop g++ 2.sy.o libtime.a libweb.a -o test ➜ Desktop ./test init web framework 123 345 socket id is 0 url is: file.ketanetwork.cc port is: 443 socket connected sending get request response is:
302 Found

302 Found


nginx

➜ Desktop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
  - 可选择生成LLVM IR语法
```lldb
 ModuleID = 'cn.MetaNetworks.sysycompiler'
source_filename = "cn.MetaNetworks.sysycompiler"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin19.6.0"

@_str_49 = private unnamed_addr constant [19 x i8] c"init web framework\00", align 1
@_str_50 = private unnamed_addr constant [4 x i8] c"123\00", align 1
@_str_51 = private unnamed_addr constant [4 x i8] c"345\00", align 1
@_str_52 = private unnamed_addr constant [13 x i8] c"socket id is\00", align 1
@_str_53 = private unnamed_addr constant [17 x i8] c"file.ketanetwork.cc\00", align 1
@_str_54 = private unnamed_addr constant [4 x i8] c"443\00", align 1
@_str_55 = private unnamed_addr constant [8 x i8] c"url is:\00", align 1
@_str_56 = private unnamed_addr constant [10 x i8] c" port is:\00", align 1
@_str_57 = private unnamed_addr constant [17 x i8] c"socket connected\00", align 1
@_str_58 = private unnamed_addr constant [20 x i8] c"sending get request\00", align 1
@_str_59 = private unnamed_addr constant [2 x i8] c"/\00", align 1
@_str_60 = private unnamed_addr constant [13 x i8] c"response is:\00", align 1

define i32 @main() {
jintao_entry:
  %0 = alloca i32, align 4
  store i32 0, i32* %0, align 4
  %1 = tail call i32 @sleep(i32 1)
  %2 = alloca [11 x i8], align 1
  store [11 x i8] c"%s %s %s \0A\00", [11 x i8]* %2, align 1
  %3 = bitcast [11 x i8]* %2 to i8*
  %echo = call i32 (i8*, ...) @printf(i8* %3, i8* getelementptr inbounds ([19 x i8], [19 x i8]* @_str_49, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_str_50, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_str_51, i32 0, i32 0))
  %4 = alloca i32, align 4
  %5 = call i32 @_web_getSocket()
  store i32 %5, i32* %4, align 4
  %6 = alloca [8 x i8], align 1
  store [8 x i8] c"%s %d \0A\00", [8 x i8]* %6, align 1
  %7 = bitcast [8 x i8]* %6 to i8*
  %echo1 = call i32 (i8*, ...) @printf(i8* %7, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @_str_52, i32 0, i32 0), i32 %5)
  %8 = alloca i8*, align 8
  store i8* getelementptr inbounds ([17 x i8], [17 x i8]* @_str_53, i32 0, i32 0), i8** %8, align 8
  %9 = alloca i8*, align 8
  store i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_str_54, i32 0, i32 0), i8** %9, align 8
  %10 = alloca [14 x i8], align 1
  store [14 x i8] c"%s %s %s %s \0A\00", [14 x i8]* %10, align 1
  %11 = bitcast [14 x i8]* %10 to i8*
  %echo2 = call i32 (i8*, ...) @printf(i8* %11, i8* getelementptr inbounds ([8 x i8], [8 x i8]* @_str_55, i32 0, i32 0), i8* getelementptr inbounds ([17 x i8], [17 x i8]* @_str_53, i32 0, i32 0), i8* getelementptr inbounds ([10 x i8], [10 x i8]* @_str_56, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_str_54, i32 0, i32 0))
  %12 = alloca i32, align 4
  %13 = call i32 @_web_connectSocket(i32 %5, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @_str_53, i32 0, i32 0), i8* getelementptr inbounds ([4 x i8], [4 x i8]* @_str_54, i32 0, i32 0))
  store i32 %13, i32* %12, align 4
  %14 = call i32 @_web_isSocketConnected(i32 %5)
  store i32 %14, i32* %12, align 4
  %equ = icmp eq i32 %14, 0
  br i1 %equ, label %neuq_jintao_if_true, label %neuq_jintao_if_end

neuq_jintao_if_true:                              ; preds = %jintao_entry
  %15 = alloca [5 x i8], align 1
  store [5 x i8] c"%s \0A\00", [5 x i8]* %15, align 1
  %16 = bitcast [5 x i8]* %15 to i8*
  %echo4 = call i32 (i8*, ...) @printf(i8* %16, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @_str_57, i32 0, i32 0))
  %17 = alloca [5 x i8], align 1
  store [5 x i8] c"%s \0A\00", [5 x i8]* %17, align 1
  %18 = bitcast [5 x i8]* %17 to i8*
  %echo5 = call i32 (i8*, ...) @printf(i8* %18, i8* getelementptr inbounds ([20 x i8], [20 x i8]* @_str_58, i32 0, i32 0))
  %19 = alloca i8*, align 8
  %20 = call i8* @_web_callGetRequest(i32 %5, i8* getelementptr inbounds ([17 x i8], [17 x i8]* @_str_53, i32 0, i32 0), i8* getelementptr inbounds ([2 x i8], [2 x i8]* @_str_59, i32 0, i32 0))
  store i8* %20, i8** %19, align 8
  %21 = alloca [5 x i8], align 1
  store [5 x i8] c"%s \0A\00", [5 x i8]* %21, align 1
  %22 = bitcast [5 x i8]* %21 to i8*
  %echo6 = call i32 (i8*, ...) @printf(i8* %22, i8* getelementptr inbounds ([13 x i8], [13 x i8]* @_str_60, i32 0, i32 0))
  %23 = alloca [5 x i8], align 1
  store [5 x i8] c"%s \0A\00", [5 x i8]* %23, align 1
  %24 = bitcast [5 x i8]* %23 to i8*
  %echo7 = call i32 (i8*, ...) @printf(i8* %24, i8* %20)
  br label %neuq_jintao_if_end

neuq_jintao_if_end:                               ; preds = %neuq_jintao_if_true, %jintao_entry
  %25 = call i32 @_web_closeSocket(i32 %5)
  store i32 0, i32* %0, align 4
  ret i32 0
}

declare i32 @sleep(i32)

declare i32 @printf(i8*, ...)

declare i32 @_web_getSocket()

declare i32 @_web_connectSocket(i32, i8*, i8*)

declare i32 @_web_isSocketConnected(i32)

declare i8* @_web_callGetRequest(i32, i8*, i8*)

declare i32 @_web_closeSocket(i32)

; Function Attrs: nounwind
declare void @llvm.stackprotector(i8*, i8**) #0

attributes #0 = { nounwind }
  • 可选择生成可读汇编代码 ```asm .section __TEXT,__text,regular,pure_instructions .build_version macos, 10, 15 .globl _main .p2align 4, 0x90 _main: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset %rbp, -16 movq %rsp, %rbp .cfi_def_cfa_register %rbp pushq %r15 pushq %r14 pushq %r12 pushq %rbx subq $80, %rsp .cfi_offset %rbx, -48 .cfi_offset %r12, -40 .cfi_offset %r14, -32 .cfi_offset %r15, -24 movl $0, -48(%rbp) movl $169898789, -37(%rbp) movb $0, -33(%rbp) leaq L__str_39(%rip), %rsi leaq -37(%rbp), %rdi xorl %eax, %eax callq _printf movl $1, %edi callq _sleep movabsq $8297073567416218405, %r12 movq %r12, -59(%rbp) movw $2592, -51(%rbp) movb $0, -49(%rbp) leaq L__str_40(%rip), %rsi leaq L__str_41(%rip), %rdx leaq L__str_42(%rip), %rcx leaq -59(%rbp), %rdi xorl %eax, %eax callq _printf callq __web_getSocket movl %eax, %r14d movl %eax, -80(%rbp) movabsq $2850364258808613, %rax movq %rax, -88(%rbp) leaq L__str_43(%rip), %rsi leaq -88(%rbp), %rdi movl %r14d, %edx xorl %eax, %eax callq _printf leaq L__str_44(%rip), %r15 movq %r15, -104(%rbp) leaq L__str_45(%rip), %rbx movq %rbx, -96(%rbp) movq %r12, -73(%rbp) movl $544417056, -65(%rbp) movw $10, -61(%rbp) leaq L__str_46(%rip), %rsi leaq L__str_47(%rip), %rcx leaq -73(%rbp), %rdi movq %r15, %rdx movq %rbx, %r8 xorl %eax, %eax callq _printf movl %r14d, %edi movq %r15, %rsi movq %rbx, %rdx callq __web_connectSocket movl %eax, -44(%rbp) movl %r14d, %edi callq __web_isSocketConnected movl %eax, -44(%rbp) testl %eax, %eax jne LBB0_2 movq %rsp, %rax leaq -16(%rax), %rdi movq %rdi, %rsp movb $0, -12(%rax) movl $169898789, -16(%rax) leaq L__str_48(%rip), %rsi xorl %eax, %eax callq _printf movq %rsp, %rax leaq -16(%rax), %rdi movq %rdi, %rsp movb $0, -12(%rax) movl $169898789, -16(%rax) leaq L__str_49(%rip), %rsi xorl %eax, %eax callq _printf movq %rsp, %rbx leaq -16(%rbx), %rsp leaq L__str_44(%rip), %rsi leaq L__str_50(%rip), %rdx movl %r14d, %edi callq __web_callGetRequest movq %rax, %r15 movq %rax, -16(%rbx) movq %rsp, %rax leaq -16(%rax), %rdi movq %rdi, %rsp movb $0, -12(%rax) movl $169898789, -16(%rax) leaq L__str_51(%rip), %rsi xorl %eax, %eax callq _printf movq %rsp, %rax leaq -16(%rax), %rdi movq %rdi, %rsp movb $0, -12(%rax) movl $169898789, -16(%rax) movq %r15, %rsi xorl %eax, %eax callq _printf LBB0_2: movl %r14d, %edi callq __web_closeSocket movl $0, -48(%rbp) xorl %eax, %eax leaq -32(%rbp), %rsp popq %rbx popq %r12 popq %r14 popq %r15 popq %rbp retq .cfi_endproc

.section __TEXT,__cstring,cstring_literals L__str_39: .asciz “\347\235\241\347\234\2401s…”

L__str_40: .asciz “init web framework”

L__str_41: .asciz “123”

L__str_42: .asciz “345”

L__str_43: .asciz “socket id is”

L__str_44: .asciz “file.ketanetwork.cc”

L__str_45: .asciz “443”

L__str_46: .asciz “url is:”

L__str_47: .asciz “ port is:”

L__str_48: .asciz “socket connected”

L__str_49: .asciz “sending get request”

L__str_50: .asciz “/”

L__str_51: .asciz “response is:”

.subsections_via_symbols

```