Skip to content
This repository was archived by the owner on Jan 8, 2023. It is now read-only.

Commit 62f7597

Browse files
author
ApsarasX
committed
feat(WIP): add builtin string type
1 parent 9a754e3 commit 62f7597

File tree

19 files changed

+412
-63
lines changed

19 files changed

+412
-63
lines changed

.github/workflows/build.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ jobs:
2424
compiler:
2525
- { cc: gcc, cxx: g++ }
2626
- { cc: clang, cxx: clang++ }
27+
fail-fast: false
2728
steps:
2829
- name: Fetch Codebase
2930
uses: actions/checkout@v2
@@ -78,9 +79,10 @@ jobs:
7879
7980
build_on_macos:
8081
name: Build on macOS
81-
runs-on: macos-10.15
82+
runs-on: ${{ matrix.os }}
8283
strategy:
8384
matrix:
85+
os: [ macos-10.15, macos-11.0 ]
8486
compiler:
8587
- { cc: gcc, cxx: g++ }
8688
- { cc: clang, cxx: clang++ }

CMakeLists.txt

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ set(CMAKE_CXX_STANDARD 17)
66

77
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
88

9+
configure_file(include/config.h.in ${PROJECT_BINARY_DIR}/include/config.h)
10+
911
include(AddANTLR)
1012

1113
include(AddLLVM)
1214

1315
include(AddDoxygen)
1416

15-
include_directories(${PROJECT_SOURCE_DIR}/include)
17+
include_directories(${PROJECT_BINARY_DIR}/include)
18+
19+
include_directories(include)
20+
21+
add_subdirectory(lib)
1622

17-
add_subdirectory(lib)
23+
add_subdirectory(external)

ROADMAP-zh_CN.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
- [x] 类型检查
1313
- [x] 变量/常量类型推导
1414
- [x] 变量/常量赋值类型检查
15-
- [x] 函数传参类型检查
15+
- [x] 函数传参/返回类型检查
1616
- [ ] 语义合法性检查
1717
- [x] break/continue语句只能出现在循环里
1818
- [x] return语句只能出现在函数里

cmake/AddLLVM.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ include_directories(${LLVM_INCLUDE_DIRS})
88

99
add_definitions(${LLVM_DEFINITIONS})
1010

11-
llvm_map_components_to_libnames(llvm_libs support core orcjit nativecodegen)
11+
llvm_map_components_to_libnames(llvm_libs support core irreader linker orcjit nativecodegen)

examples/all.ss

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
let v = 20;
1+
let v = 20 + 1;
2+
const s = "string content";
3+
let f = true;
24

35
function test() {
46
return;
57
}
68

79
function func(a: number, b: number): number {
10+
let s = "chenwengang";
811
let x = a + 1;
912
let y = b - 1;
1013
if (x < y) {

examples/variable.ss

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
let xn: number;
22
let xb: boolean;
3-
4-
const yn: number;
5-
const yb: boolean;
6-
3+
let xs: string;
74
let a: number = 1;
85
let b: boolean = false;
9-
6+
let c: string = "string content";
107
let d = 1;
118
let e = false;
12-
9+
let f = "string content";
1310
const g: number = 1;
1411
const h: boolean = false;
15-
12+
const i: string = "string content";
1613
const j = 1;
1714
const k = false;
15+
const l = "string content";

external/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
set(EXTERNAL_BITCODE ss_string.bc)
2+
3+
add_custom_command(
4+
OUTPUT ${EXTERNAL_BITCODE}
5+
COMMAND clang -c -emit-llvm ${PROJECT_SOURCE_DIR}/external/ss_string.c -std=c99 -Og -o ss_string.bc
6+
)
7+
8+
add_custom_target(
9+
external_bitcode
10+
DEPENDS ${EXTERNAL_BITCODE}
11+
)

external/ss_string.c

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#include <sys/types.h>
2+
#include <stdlib.h>
3+
#include <stdio.h>
4+
#include <string.h>
5+
#include <ctype.h>
6+
#define KEEPALIVE __attribute__((used))
7+
8+
typedef struct {
9+
char *buffer;
10+
size_t size;
11+
size_t capacity;
12+
} ss_string;
13+
14+
size_t KEEPALIVE ss_string_get_capacity_with_size(size_t size) {
15+
if (size == 0) {
16+
return 16;
17+
} else if (size < 16) {
18+
return 32;
19+
} else if (size < 32) {
20+
return 48;
21+
} else {
22+
return size * 3 / 2;
23+
}
24+
}
25+
26+
ss_string* KEEPALIVE ss_string_create_with_capacity(size_t capacity) {
27+
ss_string* str = (ss_string*) malloc(sizeof(ss_string));
28+
if (!str) {
29+
return NULL;
30+
}
31+
str->buffer = (char *) calloc(capacity, 1);
32+
str->capacity = capacity;
33+
str->size = 0;
34+
memset(str->buffer, 0, capacity);
35+
return str;
36+
}
37+
38+
ss_string* KEEPALIVE ss_string_create(const char *literal) {
39+
size_t size = strlen(literal);
40+
size_t capacity = ss_string_get_capacity_with_size(size);
41+
ss_string* str = ss_string_create_with_capacity(capacity);
42+
if (!str) {
43+
return NULL;
44+
}
45+
memcpy(str->buffer, literal, size);
46+
str->size = size;
47+
return str;
48+
}
49+
50+
void KEEPALIVE ss_string_delete(ss_string* str) {
51+
free(str->buffer);
52+
free(str);
53+
}
54+
55+
size_t KEEPALIVE ss_string_get_size(ss_string* str) {
56+
return str->size;
57+
}
58+
59+
int KEEPALIVE ss_string_grow_with_capacity(ss_string* str, size_t new_capacity) {
60+
char *new_buffer = (char *) calloc(new_capacity, 1);
61+
if (!new_buffer) {
62+
return -1;
63+
}
64+
memset(new_buffer, 0, new_capacity);
65+
memcpy(new_buffer, str->buffer, str->size);
66+
free(str->buffer);
67+
str->buffer = new_buffer;
68+
str->capacity = new_capacity;
69+
return 0;
70+
}
71+
72+
int KEEPALIVE ss_string_grow(ss_string* str) {
73+
if (str->capacity < 32) {
74+
str->capacity += 16;
75+
} else {
76+
str->capacity = str->capacity * 3 / 2;
77+
}
78+
return ss_string_grow_with_capacity(str, str->capacity);
79+
}
80+
81+
int KEEPALIVE ss_string_append_with_literal(ss_string* str, const char *literal) {
82+
size_t literal_size = strlen(literal);
83+
size_t needed_size = str->size + literal_size;
84+
size_t needed_capacity = ss_string_get_capacity_with_size(needed_size);
85+
if (str->capacity < needed_capacity) {
86+
if (ss_string_grow_with_capacity(str, needed_capacity) == -1) {
87+
return -1;
88+
}
89+
}
90+
strncat(str->buffer, literal, literal_size);
91+
str->size = needed_size;
92+
return 0;
93+
}
94+
95+
int KEEPALIVE ss_string_append(ss_string* dest, ss_string* src) {
96+
return ss_string_append_with_literal(dest, src->buffer);
97+
}
98+
99+
int KEEPALIVE ss_string_prepend_with_literal(ss_string* str, const char *literal) {
100+
size_t literal_size = strlen(literal);
101+
size_t needed_size = str->size + literal_size;
102+
size_t needed_capacity = ss_string_get_capacity_with_size(needed_size);
103+
if (str->capacity < needed_capacity) {
104+
if (ss_string_grow_with_capacity(str, needed_capacity) == -1) {
105+
return -1;
106+
}
107+
}
108+
memmove(str->buffer + literal_size, str->buffer, literal_size + 1);
109+
memcpy(str->buffer, literal, literal_size);
110+
str->size = needed_size;
111+
return 0;
112+
}
113+
114+
int KEEPALIVE ss_string_prepend(ss_string* dest, ss_string* src) {
115+
return ss_string_prepend_with_literal(dest, src->buffer);
116+
}
117+
118+
ss_string* KEEPALIVE ss_string_slice(ss_string* str, ssize_t from, ssize_t to) {
119+
if (from < 0) {
120+
from = str->size + from;
121+
}
122+
if (to < 0) {
123+
to = str->size + to;
124+
}
125+
if (to < from) {
126+
return NULL;
127+
}
128+
size_t slice_size = to - from;
129+
size_t new_capacity = ss_string_get_capacity_with_size(slice_size);
130+
ss_string* new_str = ss_string_create_with_capacity(new_capacity);
131+
memcpy(new_str->buffer, str->buffer + from, slice_size);
132+
new_str->size = slice_size;
133+
return new_str;
134+
}
135+
136+
int KEEPALIVE ss_string_equals(ss_string* str1, ss_string* str2) {
137+
size_t max_size = str1->size > str2->size ? str1->size : str2->size;
138+
return strncmp(str1->buffer, str2->buffer, max_size) == 0;
139+
}
140+
141+
ssize_t KEEPALIVE ss_string_index_of_with_literal(ss_string* str, const char *literal) {
142+
char *sub = strstr(str->buffer, literal);
143+
if (!sub) {
144+
return -1;
145+
}
146+
return sub - str->buffer;
147+
}
148+
149+
ssize_t KEEPALIVE ss_string_index_of(ss_string* str, ss_string* substr) {
150+
return ss_string_index_of_with_literal(str, substr->buffer);
151+
}
152+
153+
int KEEPALIVE ss_string_trim_left(ss_string* str) {
154+
size_t i = 0;
155+
while (isspace(str->buffer[i])) {
156+
i += 1;
157+
}
158+
char *new_buffer = (char *) calloc(str->capacity, 1);
159+
if (!new_buffer) {
160+
return -1;
161+
}
162+
memset(new_buffer, 0, str->capacity);
163+
memcpy(new_buffer, str->buffer + i, str->size - i);
164+
free(str->buffer);
165+
str->buffer = new_buffer;
166+
str->size -= i;
167+
return 0;
168+
}
169+
170+
void KEEPALIVE ss_string_trim_right(ss_string* str) {
171+
ssize_t i = str->size - 1;
172+
while (i >= 0 && isspace(str->buffer[i])) {
173+
str->buffer[i] = 0;
174+
i -= 1;
175+
}
176+
str->size = i + 1;
177+
}
178+
179+
int KEEPALIVE ss_string_trim(ss_string* str) {
180+
ss_string_trim_right(str);
181+
return ss_string_trim_left(str);
182+
}
183+
184+
void KEEPALIVE ss_console_log(ss_string *str) {
185+
printf("%s\n", str->buffer);
186+
}

include/CodeGen/Builtin.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#pragma once
2+
3+
#include <llvm/Support/SourceMgr.h>
4+
#include "config.h"
5+
#include "Util/Alias.h"
6+
#include <llvm/Linker/Linker.h>
7+
8+
struct Builtin {
9+
static void initialize(LLVMModule &destModule, LLVMContext &context);
10+
11+
static inline LLVMType *stringType = nullptr;
12+
static inline LLVMType *stringPtrType = nullptr;
13+
static inline LLVMFunction *stringCreate = nullptr;
14+
static inline LLVMFunction *stringDelete = nullptr;
15+
static inline LLVMFunction *stringGetSize = nullptr;
16+
static inline LLVMFunction *stringAppend = nullptr;
17+
static inline LLVMFunction *stringPrepend = nullptr;
18+
static inline LLVMFunction *stringSlice = nullptr;
19+
static inline LLVMFunction *stringEquals = nullptr;
20+
static inline LLVMFunction *stringIndexOf = nullptr;
21+
static inline LLVMFunction *stringTrimLeft = nullptr;
22+
static inline LLVMFunction *stringTrimRight = nullptr;
23+
static inline LLVMFunction *stringTrim = nullptr;
24+
};

include/CodeGen/IRGenerator.h

Lines changed: 5 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include "StaticScriptLexer.h"
44
#include "Sema/ASTVisitor.h"
5+
#include "CodeGen/Builtin.h"
56
#include "Util/Alias.h"
67
#include "Exception/CodeGenException.h"
78

@@ -60,19 +61,9 @@ class IRGenerator : public ASTVisitor {
6061
}
6162

6263
private:
63-
LLVMType *getType(const SharedPtr<BuiltinTypeNode> &builtinType) {
64-
LLVMType *type = llvmIRBuilder.getVoidTy();
65-
if (builtinType == BuiltinTypeNode::BOOLEAN_TYPE) {
66-
type = llvmIRBuilder.getInt1Ty();
67-
} else if (builtinType == BuiltinTypeNode::INTEGER_TYPE) {
68-
type = llvmIRBuilder.getInt64Ty();
69-
} else {
70-
// TODO: 字符串类型
71-
}
72-
return type;
73-
}
64+
LLVMType *getType(const SharedPtr<BuiltinTypeNode> &builtinType);
7465

75-
void setFuncInsertPoint(LLVMFunction *func) {
66+
inline void setFuncInsertPoint(LLVMFunction *func) {
7667
LLVMBasicBlock *curBB = &(func->getBasicBlockList().back());
7768
llvmIRBuilder.SetInsertPoint(curBB);
7869
}
@@ -81,30 +72,9 @@ class IRGenerator : public ASTVisitor {
8172
return LLVMBasicBlock::Create(llvmContext, name, parent, before);
8273
}
8374

84-
void emitBlock(LLVMBasicBlock *bb, bool isFinished = false) {
85-
LLVMBasicBlock *curBB = llvmIRBuilder.GetInsertBlock();
86-
emitBranch(bb);
87-
if (isFinished && bb->use_empty()) {
88-
delete bb;
89-
return;
90-
}
91-
if (curBB && curBB->getParent()) {
92-
curFn->getBasicBlockList().insertAfter(curBB->getIterator(), bb);
93-
} else {
94-
curFn->getBasicBlockList().push_back(bb);
95-
}
96-
llvmIRBuilder.SetInsertPoint(bb);
97-
}
98-
99-
void emitBranch(LLVMBasicBlock *targetBB) {
100-
LLVMBasicBlock *curBB = llvmIRBuilder.GetInsertBlock();
101-
if (!curBB || curBB->getTerminator()) {
75+
void emitBlock(LLVMBasicBlock *bb, bool isFinished = false);
10276

103-
} else {
104-
llvmIRBuilder.CreateBr(targetBB);
105-
}
106-
llvmIRBuilder.ClearInsertionPoint();
107-
}
77+
void emitBranch(LLVMBasicBlock *targetBB);
10878

10979
LLVMContext llvmContext;
11080
LLVMIRBuilder llvmIRBuilder;

0 commit comments

Comments
 (0)