first commit
This commit is contained in:
commit
21f61cdf76
30 changed files with 1687 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
*.o
|
||||
compiler
|
||||
example
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "slibs"]
|
||||
path = slibs
|
||||
url = https://git.samahh.dev/sam/slibs
|
21
Makefile
Normal file
21
Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
BINARY=compiler
|
||||
|
||||
CC=gcc
|
||||
CFLAGS=-O3 -Iinclude
|
||||
LDFLAGS=-Llib -ltcc
|
||||
|
||||
CFILES=$(shell find -L src -type f -name '*.c')
|
||||
OBJ=$(CFILES:.c=.o)
|
||||
|
||||
$(BINARY): $(OBJ) Makefile
|
||||
$(CC) $(OBJ) $(LDFLAGS) -o $@
|
||||
|
||||
%.o: %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
|
||||
run: $(BINARY)
|
||||
./$(BINARY) example.lisp example
|
||||
./example
|
||||
|
||||
clean:
|
||||
rm -rf $(OBJ) $(BINARY) example
|
1
example.lisp
Executable file
1
example.lisp
Executable file
|
@ -0,0 +1 @@
|
|||
(print_str "guh")
|
37
include/ast.h
Normal file
37
include/ast.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <slibs/slibs.h>
|
||||
#include <tokenizer.h>
|
||||
|
||||
#ifndef __AST_H__
|
||||
#define __AST_H__
|
||||
|
||||
extern const char* ASTTypeText[];
|
||||
|
||||
typedef enum ASTType {
|
||||
AST_PROGRAM,
|
||||
AST_CALL_EXPRESSION,
|
||||
AST_NUMBER_LITERAL,
|
||||
AST_STRING_LITERAL
|
||||
} ASTType;
|
||||
|
||||
typedef sl_vec(struct ASTNode*) ASTVec;
|
||||
|
||||
typedef struct ASTNode {
|
||||
ASTType type;
|
||||
const char* name;
|
||||
const char* value;
|
||||
|
||||
ASTVec body;
|
||||
ASTVec params;
|
||||
} ASTNode;
|
||||
|
||||
ASTNode* ast_parse(Token** token);
|
||||
ASTNode* ast_walk(Token** token);
|
||||
void ast_print(ASTNode* node, int indent);
|
||||
void ast_step(Token** token);
|
||||
ASTNode* ast_create_empty(ASTType type);
|
||||
ASTNode* ast_create_program(ASTVec body);
|
||||
ASTNode* ast_create_call_expression(const char* name, ASTVec params);
|
||||
ASTNode* ast_create_number_literal(const char* value);
|
||||
ASTNode* ast_create_string_literal(const char* value);
|
||||
|
||||
#endif
|
8
include/codegen.h
Normal file
8
include/codegen.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include <ast.h>
|
||||
|
||||
#ifndef __CODEGEN_H__
|
||||
#define __CODEGEN_H__
|
||||
|
||||
const char* codegen(ASTNode* node);
|
||||
|
||||
#endif
|
18
include/regexp.h
Normal file
18
include/regexp.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#include <regex.h>
|
||||
#include <slibs/slibs.h>
|
||||
|
||||
#ifndef __REGEXP_H__
|
||||
#define __REGEXP_H__
|
||||
|
||||
typedef int (*match_func)(regex_t, char, char**);
|
||||
|
||||
regex_t regex_create(const char* pattern, int flags);
|
||||
int match_char(regex_t regex, char c);
|
||||
sl_string collect_until(match_func matcher, regex_t regex, char** input);
|
||||
sl_string collect_until_match(regex_t regex, char** input);
|
||||
sl_string collect_until_no_match(regex_t regex, char** input);
|
||||
sl_string collect_until_match_escapable(regex_t regex, char** input);
|
||||
sl_string collect_until_no_match_escapable(regex_t regex, char** input);
|
||||
void regex_step(char** input, char* c);
|
||||
|
||||
#endif
|
208
include/slibs/slibs.h
Normal file
208
include/slibs/slibs.h
Normal file
|
@ -0,0 +1,208 @@
|
|||
#ifndef SLIBS_H
|
||||
#define SLIBS_H
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// Miscellaneous
|
||||
|
||||
#define sl_auto(name, x) typeof(x) name = x
|
||||
|
||||
#define sl_new(type, ...) \
|
||||
({ \
|
||||
type *ptr = malloc(sizeof(type)); \
|
||||
*ptr = (type){__VA_ARGS__}; \
|
||||
ptr; \
|
||||
})
|
||||
|
||||
#define sl_init(type, ...) \
|
||||
(type) { __VA_ARGS__ }
|
||||
|
||||
#define sl_array_len(arr) sizeof(arr) / sizeof(arr[0])
|
||||
|
||||
#define sl_fmt_spec(arg) \
|
||||
_Generic((arg), \
|
||||
int8_t: "%d", \
|
||||
int16_t: "%d", \
|
||||
int32_t: "%d", \
|
||||
int64_t: "%lld", \
|
||||
uint8_t: "%u", \
|
||||
uint16_t: "%u", \
|
||||
uint32_t: "%lu", \
|
||||
uint64_t: "%llu", \
|
||||
double: "%lf", \
|
||||
float: "%f", \
|
||||
char: "%c", \
|
||||
char *: "%s", \
|
||||
void *: "%p", \
|
||||
default: "Unknown")
|
||||
|
||||
#define sl_stringify(x) #x
|
||||
|
||||
// Vector
|
||||
|
||||
#define sl_vec(type) \
|
||||
struct \
|
||||
{ \
|
||||
type *data; \
|
||||
size_t size; \
|
||||
size_t capacity; \
|
||||
}
|
||||
|
||||
#define sl_vec_grow(vec) \
|
||||
{ \
|
||||
(vec).capacity = (vec).capacity * 2 + 1; \
|
||||
void *ptr = realloc((vec).data, (vec).capacity * sizeof(*(vec).data)); \
|
||||
if (ptr) \
|
||||
(vec).data = ptr; \
|
||||
}
|
||||
|
||||
#define sl_vec_push(vec, element) \
|
||||
{ \
|
||||
if ((vec).size >= (vec).capacity) \
|
||||
sl_vec_grow(vec); \
|
||||
(vec).data[(vec).size++] = (element); \
|
||||
}
|
||||
|
||||
#define sl_vec_shift(vec, element) \
|
||||
{ \
|
||||
if ((vec).size >= (vec).capacity) \
|
||||
sl_vec_grow(vec); \
|
||||
memmove((vec).data + 1, (vec).data, (vec).size * sizeof(*(vec).data)); \
|
||||
(vec).data[0] = (element); \
|
||||
(vec).size++; \
|
||||
}
|
||||
|
||||
#define sl_vec_pop(vec) \
|
||||
{ \
|
||||
if ((vec).size > 0) \
|
||||
{ \
|
||||
(vec).size--; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define sl_vec_at(vec, index) ((vec).data[index])
|
||||
|
||||
#define sl_vec_size(vec) ((vec).size)
|
||||
|
||||
#define sl_vec_capacity(vec) ((vec).capacity)
|
||||
|
||||
#define sl_vec_free(vec) free((vec).data)
|
||||
|
||||
#define sl_vec_begin(vec) (vec).data
|
||||
|
||||
#define sl_vec_end(vec) ((vec).data + (vec).size)
|
||||
|
||||
#define sl_vec_it(name, vec) \
|
||||
sl_auto((name), sl_vec_begin(vec)); \
|
||||
(name) != sl_vec_end(vec); \
|
||||
++(name)
|
||||
|
||||
// String
|
||||
|
||||
typedef sl_vec(char) sl_string;
|
||||
|
||||
#define sl_string(c_str) \
|
||||
({ \
|
||||
sl_string str = {0}; \
|
||||
for (size_t i = 0; i < strlen((c_str)); i++) \
|
||||
sl_vec_push(str, (c_str)[i]); \
|
||||
str; \
|
||||
})
|
||||
|
||||
#define sl_tostring(val) \
|
||||
({ \
|
||||
sl_auto(len, snprintf(NULL, 0, sl_fmt_spec(val), val) + 1); \
|
||||
sl_auto(buf, (char *)malloc(len)); \
|
||||
snprintf(buf, len, sl_fmt_spec(val), val); \
|
||||
sl_auto(str, sl_string(buf)); \
|
||||
free(buf); \
|
||||
str; \
|
||||
})
|
||||
|
||||
#define sl_str_free(str) sl_vec_free(str)
|
||||
|
||||
#define sl_c_str(str) \
|
||||
({ \
|
||||
sl_vec_push((str), '\0'); \
|
||||
(str).size--; \
|
||||
(str).data; \
|
||||
})
|
||||
|
||||
void sl_append_c_str(sl_string* sl_str, const char* c_str);
|
||||
|
||||
#ifdef SL_IMPLEMENTATION
|
||||
void sl_append_c_str(sl_string* sl_str, const char* c_str) {
|
||||
for(int i = 0; i < strlen(c_str); i++) {
|
||||
sl_vec_push(*sl_str, c_str[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Pointers
|
||||
|
||||
#define sl_ptr(type) \
|
||||
struct \
|
||||
{ \
|
||||
type *ptr; \
|
||||
int ref_count; \
|
||||
}
|
||||
|
||||
#define sl_ptr_make(raw_ptr) \
|
||||
{ \
|
||||
raw_ptr, 1 \
|
||||
}
|
||||
|
||||
#define sl_ptr_release(smart_ptr) \
|
||||
({ \
|
||||
smart_ptr.ref_count--; \
|
||||
if (smart_ptr.ref_count <= 0) \
|
||||
{ \
|
||||
free(smart_ptr.ptr); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define sl_ptr_get(smart_ptr, raw_ptr_name, scope) \
|
||||
({ \
|
||||
assert(smart_ptr.ref_count > 0 && "Smart pointer already released!"); \
|
||||
sl_auto(raw_ptr_name, smart_ptr.ptr); \
|
||||
smart_ptr.ref_count++; \
|
||||
scope; \
|
||||
sl_ptr_release(smart_ptr); \
|
||||
});
|
||||
|
||||
#define sl_ptr_scope(smart_ptr, scope) \
|
||||
({ \
|
||||
scope; \
|
||||
sl_ptr_release(smart_ptr); \
|
||||
});
|
||||
|
||||
void sl_read_file(const char *filename, sl_string *buffer);
|
||||
|
||||
#ifdef SL_IMPLEMENTATION
|
||||
void sl_read_file(const char *filename, sl_string *buffer)
|
||||
{
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (!file)
|
||||
{
|
||||
fprintf(stderr, "Error: could not open file %s\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
size_t file_size = ftell(file);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
|
||||
for (size_t i = 0; i < file_size; i++)
|
||||
{
|
||||
sl_vec_push(*buffer, fgetc(file));
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // SLIBS_H
|
116
include/tcc/libtcc.h
Normal file
116
include/tcc/libtcc.h
Normal file
|
@ -0,0 +1,116 @@
|
|||
#ifndef LIBTCC_H
|
||||
#define LIBTCC_H
|
||||
|
||||
#ifndef LIBTCCAPI
|
||||
# define LIBTCCAPI
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*****************************/
|
||||
/* set custom allocator for all allocations (optional), NULL for default. */
|
||||
typedef void *TCCReallocFunc(void *ptr, unsigned long size);
|
||||
LIBTCCAPI void tcc_set_realloc(TCCReallocFunc *my_realloc);
|
||||
|
||||
/*****************************/
|
||||
typedef struct TCCState TCCState;
|
||||
|
||||
/* create a new TCC compilation context */
|
||||
LIBTCCAPI TCCState *tcc_new(void);
|
||||
|
||||
/* free a TCC compilation context */
|
||||
LIBTCCAPI void tcc_delete(TCCState *s);
|
||||
|
||||
/* set CONFIG_TCCDIR at runtime */
|
||||
LIBTCCAPI void tcc_set_lib_path(TCCState *s, const char *path);
|
||||
|
||||
/* set error/warning callback (optional) */
|
||||
typedef void TCCErrorFunc(void *opaque, const char *msg);
|
||||
LIBTCCAPI void tcc_set_error_func(TCCState *s, void *error_opaque, TCCErrorFunc *error_func);
|
||||
|
||||
/* set options as from command line (multiple supported) */
|
||||
LIBTCCAPI int tcc_set_options(TCCState *s, const char *str);
|
||||
|
||||
/*****************************/
|
||||
/* preprocessor */
|
||||
|
||||
/* add include path */
|
||||
LIBTCCAPI int tcc_add_include_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* add in system include path */
|
||||
LIBTCCAPI int tcc_add_sysinclude_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* define preprocessor symbol 'sym'. value can be NULL, sym can be "sym=val" */
|
||||
LIBTCCAPI void tcc_define_symbol(TCCState *s, const char *sym, const char *value);
|
||||
|
||||
/* undefine preprocess symbol 'sym' */
|
||||
LIBTCCAPI void tcc_undefine_symbol(TCCState *s, const char *sym);
|
||||
|
||||
/*****************************/
|
||||
/* compiling */
|
||||
|
||||
/* add a file (C file, dll, object, library, ld script). Return -1 if error. */
|
||||
LIBTCCAPI int tcc_add_file(TCCState *s, const char *filename);
|
||||
|
||||
/* compile a string containing a C source. Return -1 if error. */
|
||||
LIBTCCAPI int tcc_compile_string(TCCState *s, const char *buf);
|
||||
|
||||
/* Tip: to have more specific errors/warnings from tcc_compile_string(),
|
||||
you can prefix the string with "#line <num> \"<filename>\"\n" */
|
||||
|
||||
/*****************************/
|
||||
/* linking commands */
|
||||
|
||||
/* set output type. MUST BE CALLED before any compilation */
|
||||
LIBTCCAPI int tcc_set_output_type(TCCState *s, int output_type);
|
||||
#define TCC_OUTPUT_MEMORY 1 /* output will be run in memory */
|
||||
#define TCC_OUTPUT_EXE 2 /* executable file */
|
||||
#define TCC_OUTPUT_DLL 4 /* dynamic library */
|
||||
#define TCC_OUTPUT_OBJ 3 /* object file */
|
||||
#define TCC_OUTPUT_PREPROCESS 5 /* only preprocess */
|
||||
|
||||
/* equivalent to -Lpath option */
|
||||
LIBTCCAPI int tcc_add_library_path(TCCState *s, const char *pathname);
|
||||
|
||||
/* the library name is the same as the argument of the '-l' option */
|
||||
LIBTCCAPI int tcc_add_library(TCCState *s, const char *libraryname);
|
||||
|
||||
/* add a symbol to the compiled program */
|
||||
LIBTCCAPI int tcc_add_symbol(TCCState *s, const char *name, const void *val);
|
||||
|
||||
/* output an executable, library or object file. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename);
|
||||
|
||||
/* link and run main() function and return its value. DO NOT call
|
||||
tcc_relocate() before. */
|
||||
LIBTCCAPI int tcc_run(TCCState *s, int argc, char **argv);
|
||||
|
||||
/* do all relocations (needed before using tcc_get_symbol()) */
|
||||
LIBTCCAPI int tcc_relocate(TCCState *s1);
|
||||
|
||||
/* return symbol value or NULL if not found */
|
||||
LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name);
|
||||
|
||||
/* list all (global) symbols and their values via 'symbol_cb()' */
|
||||
LIBTCCAPI void tcc_list_symbols(TCCState *s, void *ctx,
|
||||
void (*symbol_cb)(void *ctx, const char *name, const void *val));
|
||||
|
||||
/* experimental/advanced section (see libtcc_test_mt.c for an example) */
|
||||
|
||||
/* catch runtime exceptions (optionally limit backtraces at top_func),
|
||||
when using tcc_set_options("-bt") and when not using tcc_run() */
|
||||
LIBTCCAPI void *_tcc_setjmp(TCCState *s1, void *jmp_buf, void *top_func, void *longjmp);
|
||||
#define tcc_setjmp(s1,jb,f) setjmp(_tcc_setjmp(s1, jb, f, longjmp))
|
||||
|
||||
/* custom error printer for runtime exceptions. Returning 0 stops backtrace */
|
||||
typedef int TCCBtFunc(void *udata, void *pc, const char *file, int line, const char* func, const char *msg);
|
||||
LIBTCCAPI void tcc_set_backtrace_func(TCCState *s1, void* userdata, TCCBtFunc*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
25
include/tokenizer.h
Normal file
25
include/tokenizer.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef __TOKENIZER_H__
|
||||
#define __TOKENIZER_H__
|
||||
|
||||
extern const char* TokenTypeText[];
|
||||
|
||||
typedef enum TokenType {
|
||||
TOKEN_LPAREN,
|
||||
TOKEN_RPAREN,
|
||||
TOKEN_NUMBER,
|
||||
TOKEN_NAME,
|
||||
TOKEN_STRING
|
||||
} TokenType;
|
||||
|
||||
typedef struct Token {
|
||||
char* value;
|
||||
TokenType type;
|
||||
struct Token* next;
|
||||
} Token;
|
||||
|
||||
Token* tokenize(char* input);
|
||||
|
||||
Token* token_create(char* value, TokenType type, Token* root);
|
||||
Token* token_append(Token* root, Token* new_token);
|
||||
|
||||
#endif
|
BIN
lib/libtcc.a
Normal file
BIN
lib/libtcc.a
Normal file
Binary file not shown.
75
lib/tcc/include/float.h
Normal file
75
lib/tcc/include/float.h
Normal file
|
@ -0,0 +1,75 @@
|
|||
#ifndef _FLOAT_H_
|
||||
#define _FLOAT_H_
|
||||
|
||||
#define FLT_RADIX 2
|
||||
|
||||
/* IEEE float */
|
||||
#define FLT_MANT_DIG 24
|
||||
#define FLT_DIG 6
|
||||
#define FLT_ROUNDS 1
|
||||
#define FLT_EPSILON 1.19209290e-07F
|
||||
#define FLT_MIN_EXP (-125)
|
||||
#define FLT_MIN 1.17549435e-38F
|
||||
#define FLT_MIN_10_EXP (-37)
|
||||
#define FLT_MAX_EXP 128
|
||||
#define FLT_MAX 3.40282347e+38F
|
||||
#define FLT_MAX_10_EXP 38
|
||||
|
||||
/* IEEE double */
|
||||
#define DBL_MANT_DIG 53
|
||||
#define DBL_DIG 15
|
||||
#define DBL_EPSILON 2.2204460492503131e-16
|
||||
#define DBL_MIN_EXP (-1021)
|
||||
#define DBL_MIN 2.2250738585072014e-308
|
||||
#define DBL_MIN_10_EXP (-307)
|
||||
#define DBL_MAX_EXP 1024
|
||||
#define DBL_MAX 1.7976931348623157e+308
|
||||
#define DBL_MAX_10_EXP 308
|
||||
|
||||
/* horrible intel long double */
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
|
||||
#define LDBL_MANT_DIG 64
|
||||
#define LDBL_DIG 18
|
||||
#define LDBL_EPSILON 1.08420217248550443401e-19L
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MIN 3.36210314311209350626e-4932L
|
||||
#define LDBL_MIN_10_EXP (-4931)
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MAX 1.18973149535723176502e+4932L
|
||||
#define LDBL_MAX_10_EXP 4932
|
||||
#define DECIMAL_DIG 21
|
||||
|
||||
#elif defined __aarch64__ || defined __riscv
|
||||
/*
|
||||
* Use values from:
|
||||
* gcc -dM -E -xc /dev/null | grep LDBL | sed -e "s/__//g"
|
||||
*/
|
||||
#define LDBL_MANT_DIG 113
|
||||
#define LDBL_DIG 33
|
||||
#define LDBL_EPSILON 1.92592994438723585305597794258492732e-34L
|
||||
#define LDBL_MIN_EXP (-16381)
|
||||
#define LDBL_MIN 3.36210314311209350626267781732175260e-4932L
|
||||
#define LDBL_MIN_10_EXP (-4931)
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define LDBL_MAX 1.18973149535723176508575932662800702e+4932L
|
||||
#define LDBL_MAX_EXP 16384
|
||||
#define DECIMAL_DIG 36
|
||||
|
||||
#else
|
||||
|
||||
/* same as IEEE double */
|
||||
#define LDBL_MANT_DIG 53
|
||||
#define LDBL_DIG 15
|
||||
#define LDBL_EPSILON 2.2204460492503131e-16L
|
||||
#define LDBL_MIN_EXP (-1021)
|
||||
#define LDBL_MIN 2.2250738585072014e-308L
|
||||
#define LDBL_MIN_10_EXP (-307)
|
||||
#define LDBL_MAX_EXP 1024
|
||||
#define LDBL_MAX 1.7976931348623157e+308L
|
||||
#define LDBL_MAX_10_EXP 308
|
||||
#define DECIMAL_DIG 17
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _FLOAT_H_ */
|
16
lib/tcc/include/stdalign.h
Normal file
16
lib/tcc/include/stdalign.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef _STDALIGN_H
|
||||
#define _STDALIGN_H
|
||||
|
||||
#if __STDC_VERSION__ < 201112L && (defined(__GNUC__) || defined(__TINYC__))
|
||||
# define _Alignas(t) __attribute__((__aligned__(t)))
|
||||
# define _Alignof(t) __alignof__(t)
|
||||
#endif
|
||||
|
||||
#define alignas _Alignas
|
||||
#define alignof _Alignof
|
||||
|
||||
#define __alignas_is_defined 1
|
||||
#define __alignof_is_defined 1
|
||||
|
||||
#endif /* _STDALIGN_H */
|
||||
|
14
lib/tcc/include/stdarg.h
Normal file
14
lib/tcc/include/stdarg.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef _STDARG_H
|
||||
#define _STDARG_H
|
||||
|
||||
typedef __builtin_va_list va_list;
|
||||
#define va_start __builtin_va_start
|
||||
#define va_arg __builtin_va_arg
|
||||
#define va_copy __builtin_va_copy
|
||||
#define va_end __builtin_va_end
|
||||
|
||||
/* fix a buggy dependency on GCC in libio.h */
|
||||
typedef va_list __gnuc_va_list;
|
||||
#define _VA_LIST_DEFINED
|
||||
|
||||
#endif /* _STDARG_H */
|
173
lib/tcc/include/stdatomic.h
Normal file
173
lib/tcc/include/stdatomic.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* This file is derived from clang's stdatomic.h */
|
||||
|
||||
/*===---- stdatomic.h - Standard header for atomic types and operations -----===
|
||||
*
|
||||
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
* See https://llvm.org/LICENSE.txt for license information.
|
||||
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
*
|
||||
*===-----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
#ifndef _STDATOMIC_H
|
||||
#define _STDATOMIC_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define __ATOMIC_RELAXED 0
|
||||
#define __ATOMIC_CONSUME 1
|
||||
#define __ATOMIC_ACQUIRE 2
|
||||
#define __ATOMIC_RELEASE 3
|
||||
#define __ATOMIC_ACQ_REL 4
|
||||
#define __ATOMIC_SEQ_CST 5
|
||||
|
||||
/* Memory ordering */
|
||||
typedef enum {
|
||||
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||
memory_order_consume = __ATOMIC_CONSUME,
|
||||
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||
memory_order_release = __ATOMIC_RELEASE,
|
||||
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||
memory_order_seq_cst = __ATOMIC_SEQ_CST,
|
||||
} memory_order;
|
||||
|
||||
/* Atomic typedefs */
|
||||
typedef _Atomic(_Bool) atomic_bool;
|
||||
typedef _Atomic(char) atomic_char;
|
||||
typedef _Atomic(signed char) atomic_schar;
|
||||
typedef _Atomic(unsigned char) atomic_uchar;
|
||||
typedef _Atomic(short) atomic_short;
|
||||
typedef _Atomic(unsigned short) atomic_ushort;
|
||||
typedef _Atomic(int) atomic_int;
|
||||
typedef _Atomic(unsigned int) atomic_uint;
|
||||
typedef _Atomic(long) atomic_long;
|
||||
typedef _Atomic(unsigned long) atomic_ulong;
|
||||
typedef _Atomic(long long) atomic_llong;
|
||||
typedef _Atomic(unsigned long long) atomic_ullong;
|
||||
typedef _Atomic(uint_least16_t) atomic_char16_t;
|
||||
typedef _Atomic(uint_least32_t) atomic_char32_t;
|
||||
typedef _Atomic(wchar_t) atomic_wchar_t;
|
||||
typedef _Atomic(int_least8_t) atomic_int_least8_t;
|
||||
typedef _Atomic(uint_least8_t) atomic_uint_least8_t;
|
||||
typedef _Atomic(int_least16_t) atomic_int_least16_t;
|
||||
typedef _Atomic(uint_least16_t) atomic_uint_least16_t;
|
||||
typedef _Atomic(int_least32_t) atomic_int_least32_t;
|
||||
typedef _Atomic(uint_least32_t) atomic_uint_least32_t;
|
||||
typedef _Atomic(int_least64_t) atomic_int_least64_t;
|
||||
typedef _Atomic(uint_least64_t) atomic_uint_least64_t;
|
||||
typedef _Atomic(int_fast8_t) atomic_int_fast8_t;
|
||||
typedef _Atomic(uint_fast8_t) atomic_uint_fast8_t;
|
||||
typedef _Atomic(int_fast16_t) atomic_int_fast16_t;
|
||||
typedef _Atomic(uint_fast16_t) atomic_uint_fast16_t;
|
||||
typedef _Atomic(int_fast32_t) atomic_int_fast32_t;
|
||||
typedef _Atomic(uint_fast32_t) atomic_uint_fast32_t;
|
||||
typedef _Atomic(int_fast64_t) atomic_int_fast64_t;
|
||||
typedef _Atomic(uint_fast64_t) atomic_uint_fast64_t;
|
||||
typedef _Atomic(intptr_t) atomic_intptr_t;
|
||||
typedef _Atomic(uintptr_t) atomic_uintptr_t;
|
||||
typedef _Atomic(size_t) atomic_size_t;
|
||||
typedef _Atomic(ptrdiff_t) atomic_ptrdiff_t;
|
||||
typedef _Atomic(intmax_t) atomic_intmax_t;
|
||||
typedef _Atomic(uintmax_t) atomic_uintmax_t;
|
||||
|
||||
/* Atomic flag */
|
||||
typedef struct {
|
||||
atomic_bool value;
|
||||
} atomic_flag;
|
||||
|
||||
#define ATOMIC_FLAG_INIT {0}
|
||||
#define ATOMIC_VAR_INIT(value) (value)
|
||||
|
||||
#define atomic_flag_test_and_set_explicit(object, order) \
|
||||
__atomic_test_and_set((void *)(&((object)->value)), order)
|
||||
#define atomic_flag_test_and_set(object) \
|
||||
atomic_flag_test_and_set_explicit(object, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_flag_clear_explicit(object, order) \
|
||||
__atomic_clear((bool *)(&((object)->value)), order)
|
||||
#define atomic_flag_clear(object) \
|
||||
atomic_flag_clear_explicit(object, __ATOMIC_SEQ_CST)
|
||||
|
||||
/* Generic routines */
|
||||
#define atomic_init(object, desired) \
|
||||
atomic_store_explicit(object, desired, __ATOMIC_RELAXED)
|
||||
|
||||
#define atomic_store_explicit(object, desired, order) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = (desired); \
|
||||
__atomic_store (ptr, &tmp, (order)); \
|
||||
})
|
||||
#define atomic_store(object, desired) \
|
||||
atomic_store_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_load_explicit(object, order) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp; \
|
||||
__atomic_load (ptr, &tmp, (order)); \
|
||||
tmp; \
|
||||
})
|
||||
#define atomic_load(object) atomic_load_explicit (object, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_exchange_explicit(object, desired, order) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) val = (desired); \
|
||||
__typeof__ (*ptr) tmp; \
|
||||
__atomic_exchange (ptr, &val, &tmp, (order)); \
|
||||
tmp; \
|
||||
})
|
||||
#define atomic_exchange(object, desired) \
|
||||
atomic_exchange_explicit (object, desired, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_compare_exchange_strong_explicit(object, expected, desired, success, failure) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = desired; \
|
||||
__atomic_compare_exchange(ptr, expected, &tmp, 0, success, failure); \
|
||||
})
|
||||
#define atomic_compare_exchange_strong(object, expected, desired) \
|
||||
atomic_compare_exchange_strong_explicit (object, expected, desired, \
|
||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_compare_exchange_weak_explicit(object, expected, desired, success, failure) \
|
||||
({ __typeof__ (object) ptr = (object); \
|
||||
__typeof__ (*ptr) tmp = desired; \
|
||||
__atomic_compare_exchange(ptr, expected, &tmp, 1, success, failure); \
|
||||
})
|
||||
#define atomic_compare_exchange_weak(object, expected, desired) \
|
||||
atomic_compare_exchange_weak_explicit (object, expected, desired, \
|
||||
__ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
|
||||
|
||||
#define atomic_fetch_add(object, operand) \
|
||||
__atomic_fetch_add(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_add_explicit __atomic_fetch_add
|
||||
|
||||
#define atomic_fetch_sub(object, operand) \
|
||||
__atomic_fetch_sub(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_sub_explicit __atomic_fetch_sub
|
||||
|
||||
#define atomic_fetch_or(object, operand) \
|
||||
__atomic_fetch_or(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_or_explicit __atomic_fetch_or
|
||||
|
||||
#define atomic_fetch_xor(object, operand) \
|
||||
__atomic_fetch_xor(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_xor_explicit __atomic_fetch_xor
|
||||
|
||||
#define atomic_fetch_and(object, operand) \
|
||||
__atomic_fetch_and(object, operand, __ATOMIC_SEQ_CST)
|
||||
#define atomic_fetch_and_explicit __atomic_fetch_and
|
||||
|
||||
extern void atomic_thread_fence (memory_order);
|
||||
extern void __atomic_thread_fence (memory_order);
|
||||
#define atomic_thread_fence(order) __atomic_thread_fence (order)
|
||||
extern void atomic_signal_fence (memory_order);
|
||||
extern void __atomic_signal_fence (memory_order);
|
||||
#define atomic_signal_fence(order) __atomic_signal_fence (order)
|
||||
extern bool __atomic_is_lock_free(size_t size, void *ptr);
|
||||
#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
|
||||
|
||||
extern bool __atomic_test_and_set (void *, memory_order);
|
||||
extern void __atomic_clear (bool *, memory_order);
|
||||
|
||||
#endif /* _STDATOMIC_H */
|
11
lib/tcc/include/stdbool.h
Normal file
11
lib/tcc/include/stdbool.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
/* ISOC99 boolean */
|
||||
|
||||
#define bool _Bool
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif /* _STDBOOL_H */
|
41
lib/tcc/include/stddef.h
Normal file
41
lib/tcc/include/stddef.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef _STDDEF_H
|
||||
#define _STDDEF_H
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
typedef __PTRDIFF_TYPE__ ssize_t;
|
||||
typedef __WCHAR_TYPE__ wchar_t;
|
||||
typedef __PTRDIFF_TYPE__ ptrdiff_t;
|
||||
typedef __PTRDIFF_TYPE__ intptr_t;
|
||||
typedef __SIZE_TYPE__ uintptr_t;
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
typedef union { long long __ll; long double __ld; } max_align_t;
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void*)0)
|
||||
#endif
|
||||
|
||||
#undef offsetof
|
||||
#define offsetof(type, field) ((size_t)&((type *)0)->field)
|
||||
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
void *alloca(size_t size);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/* Older glibc require a wint_t from <stddef.h> (when requested
|
||||
by __need_wint_t, as otherwise stddef.h isn't allowed to
|
||||
define this type). Note that this must be outside the normal
|
||||
_STDDEF_H guard, so that it works even when we've included the file
|
||||
already (without requiring wint_t). Some other libs define _WINT_T
|
||||
if they've already provided that type, so we can use that as guard.
|
||||
TCC defines __WINT_TYPE__ for us. */
|
||||
#if defined (__need_wint_t)
|
||||
#ifndef _WINT_T
|
||||
#define _WINT_T
|
||||
typedef __WINT_TYPE__ wint_t;
|
||||
#endif
|
||||
#undef __need_wint_t
|
||||
#endif
|
7
lib/tcc/include/stdnoreturn.h
Normal file
7
lib/tcc/include/stdnoreturn.h
Normal file
|
@ -0,0 +1,7 @@
|
|||
#ifndef _STDNORETURN_H
|
||||
#define _STDNORETURN_H
|
||||
|
||||
/* ISOC11 noreturn */
|
||||
#define noreturn _Noreturn
|
||||
|
||||
#endif /* _STDNORETURN_H */
|
333
lib/tcc/include/tccdefs.h
Normal file
333
lib/tcc/include/tccdefs.h
Normal file
|
@ -0,0 +1,333 @@
|
|||
/* tccdefs.h
|
||||
|
||||
Nothing is defined before this file except target machine, target os
|
||||
and the few things related to option settings in tccpp.c:tcc_predefs().
|
||||
|
||||
This file is either included at runtime as is, or converted and
|
||||
included as C-strings at compile-time (depending on CONFIG_TCC_PREDEFS).
|
||||
|
||||
Note that line indent matters:
|
||||
|
||||
- in lines starting at column 1, platform macros are replaced by
|
||||
corresponding TCC target compile-time macros. See conftest.c for
|
||||
the list of platform macros supported in lines starting at column 1.
|
||||
|
||||
- only lines indented >= 4 are actually included into the executable,
|
||||
check tccdefs_.h.
|
||||
*/
|
||||
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
/* 32bit systems. */
|
||||
#if defined __OpenBSD__
|
||||
#define __SIZE_TYPE__ unsigned long
|
||||
#define __PTRDIFF_TYPE__ long
|
||||
#else
|
||||
#define __SIZE_TYPE__ unsigned int
|
||||
#define __PTRDIFF_TYPE__ int
|
||||
#endif
|
||||
#define __ILP32__ 1
|
||||
#define __INT64_TYPE__ long long
|
||||
#elif __SIZEOF_LONG__ == 4
|
||||
/* 64bit Windows. */
|
||||
#define __SIZE_TYPE__ unsigned long long
|
||||
#define __PTRDIFF_TYPE__ long long
|
||||
#define __LLP64__ 1
|
||||
#define __INT64_TYPE__ long long
|
||||
#else
|
||||
/* Other 64bit systems. */
|
||||
#define __SIZE_TYPE__ unsigned long
|
||||
#define __PTRDIFF_TYPE__ long
|
||||
#define __LP64__ 1
|
||||
# if defined __linux__
|
||||
#define __INT64_TYPE__ long
|
||||
# else /* APPLE, BSD */
|
||||
#define __INT64_TYPE__ long long
|
||||
# endif
|
||||
#endif
|
||||
#define __SIZEOF_INT__ 4
|
||||
#define __INT_MAX__ 0x7fffffff
|
||||
#if __SIZEOF_LONG__ == 4
|
||||
#define __LONG_MAX__ 0x7fffffffL
|
||||
#else
|
||||
#define __LONG_MAX__ 0x7fffffffffffffffL
|
||||
#endif
|
||||
#define __SIZEOF_LONG_LONG__ 8
|
||||
#define __LONG_LONG_MAX__ 0x7fffffffffffffffLL
|
||||
#define __CHAR_BIT__ 8
|
||||
#define __ORDER_LITTLE_ENDIAN__ 1234
|
||||
#define __ORDER_BIG_ENDIAN__ 4321
|
||||
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
|
||||
#if defined _WIN32
|
||||
#define __WCHAR_TYPE__ unsigned short
|
||||
#define __WINT_TYPE__ unsigned short
|
||||
#elif defined __linux__
|
||||
#define __WCHAR_TYPE__ int
|
||||
#define __WINT_TYPE__ unsigned int
|
||||
#else
|
||||
#define __WCHAR_TYPE__ int
|
||||
#define __WINT_TYPE__ int
|
||||
#endif
|
||||
|
||||
#if __STDC_VERSION__ >= 201112L
|
||||
# define __STDC_NO_ATOMICS__ 1
|
||||
# define __STDC_NO_COMPLEX__ 1
|
||||
# define __STDC_NO_THREADS__ 1
|
||||
#if !defined _WIN32
|
||||
# define __STDC_UTF_16__ 1
|
||||
# define __STDC_UTF_32__ 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined _WIN32
|
||||
#define __declspec(x) __attribute__((x))
|
||||
#define __cdecl
|
||||
|
||||
#elif defined __FreeBSD__
|
||||
#define __GNUC__ 9
|
||||
#define __GNUC_MINOR__ 3
|
||||
#define __GNUC_PATCHLEVEL__ 0
|
||||
#define __GNUC_STDC_INLINE__ 1
|
||||
#define __NO_TLS 1
|
||||
#define __RUNETYPE_INTERNAL 1
|
||||
# if __SIZEOF_POINTER__ == 8
|
||||
/* FIXME, __int128_t is used by setjump */
|
||||
#define __int128_t struct { unsigned char _dummy[16] __attribute((aligned(16))); }
|
||||
#define __SIZEOF_SIZE_T__ 8
|
||||
#define __SIZEOF_PTRDIFF_T__ 8
|
||||
#else
|
||||
#define __SIZEOF_SIZE_T__ 4
|
||||
#define __SIZEOF_PTRDIFF_T__ 4
|
||||
# endif
|
||||
|
||||
#elif defined __FreeBSD_kernel__
|
||||
|
||||
#elif defined __NetBSD__
|
||||
#define __GNUC__ 4
|
||||
#define __GNUC_MINOR__ 1
|
||||
#define __GNUC_PATCHLEVEL__ 0
|
||||
#define _Pragma(x)
|
||||
#define __ELF__ 1
|
||||
#if defined __aarch64__
|
||||
#define _LOCORE /* avoids usage of __asm */
|
||||
#endif
|
||||
|
||||
#elif defined __OpenBSD__
|
||||
#define __GNUC__ 4
|
||||
#define _ANSI_LIBRARY 1
|
||||
|
||||
#elif defined __APPLE__
|
||||
/* emulate APPLE-GCC to make libc's headerfiles compile: */
|
||||
#define __GNUC__ 4 /* darwin emits warning on GCC<4 */
|
||||
#define __APPLE_CC__ 1 /* for <TargetConditionals.h> */
|
||||
#define __LITTLE_ENDIAN__ 1
|
||||
#define _DONT_USE_CTYPE_INLINE_ 1
|
||||
/* avoids usage of GCC/clang specific builtins in libc-headerfiles: */
|
||||
#define __FINITE_MATH_ONLY__ 1
|
||||
#define _FORTIFY_SOURCE 0
|
||||
//#define __has_builtin(x) 0
|
||||
|
||||
#elif defined __ANDROID__
|
||||
#define BIONIC_IOCTL_NO_SIGNEDNESS_OVERLOAD
|
||||
|
||||
#else
|
||||
/* Linux */
|
||||
|
||||
#endif
|
||||
|
||||
/* Some derived integer types needed to get stdint.h to compile correctly on some platforms */
|
||||
#ifndef __NetBSD__
|
||||
#define __UINTPTR_TYPE__ unsigned __PTRDIFF_TYPE__
|
||||
#define __INTPTR_TYPE__ __PTRDIFF_TYPE__
|
||||
#endif
|
||||
#define __INT32_TYPE__ int
|
||||
|
||||
#if !defined _WIN32
|
||||
/* glibc defines. We do not support __USER_NAME_PREFIX__ */
|
||||
#define __REDIRECT(name, proto, alias) name proto __asm__ (#alias)
|
||||
#define __REDIRECT_NTH(name, proto, alias) name proto __asm__ (#alias) __THROW
|
||||
#define __REDIRECT_NTHNL(name, proto, alias) name proto __asm__ (#alias) __THROWNL
|
||||
#endif
|
||||
|
||||
/* not implemented */
|
||||
#define __PRETTY_FUNCTION__ __FUNCTION__
|
||||
#define __has_builtin(x) 0
|
||||
#define __has_feature(x) 0
|
||||
/* C23 Keywords */
|
||||
#define _Nonnull
|
||||
#define _Nullable
|
||||
#define _Nullable_result
|
||||
#define _Null_unspecified
|
||||
|
||||
/* skip __builtin... with -E */
|
||||
#ifndef __TCC_PP__
|
||||
|
||||
#define __builtin_offsetof(type, field) ((__SIZE_TYPE__)&((type*)0)->field)
|
||||
#define __builtin_extract_return_addr(x) x
|
||||
#if !defined __linux__ && !defined _WIN32
|
||||
/* used by math.h */
|
||||
#define __builtin_huge_val() 1e500
|
||||
#define __builtin_huge_valf() 1e50f
|
||||
#define __builtin_huge_vall() 1e5000L
|
||||
# if defined __APPLE__
|
||||
#define __builtin_nanf(ignored_string) (0.0F/0.0F)
|
||||
/* used by floats.h to implement FLT_ROUNDS C99 macro. 1 == to nearest */
|
||||
#define __builtin_flt_rounds() 1
|
||||
/* used by _fd_def.h */
|
||||
#define __builtin_bzero(p, ignored_size) bzero(p, sizeof(*(p)))
|
||||
# else
|
||||
#define __builtin_nanf(ignored_string) (0.0F/0.0F)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* __builtin_va_list */
|
||||
#if defined __x86_64__
|
||||
#if !defined _WIN32
|
||||
/* GCC compatible definition of va_list. */
|
||||
/* This should be in sync with the declaration in our lib/libtcc1.c */
|
||||
typedef struct {
|
||||
unsigned gp_offset, fp_offset;
|
||||
union {
|
||||
unsigned overflow_offset;
|
||||
char *overflow_arg_area;
|
||||
};
|
||||
char *reg_save_area;
|
||||
} __builtin_va_list[1];
|
||||
|
||||
void *__va_arg(__builtin_va_list ap, int arg_type, int size, int align);
|
||||
#define __builtin_va_start(ap, last) \
|
||||
(*(ap) = *(__builtin_va_list)((char*)__builtin_frame_address(0) - 24))
|
||||
#define __builtin_va_arg(ap, t) \
|
||||
(*(t *)(__va_arg(ap, __builtin_va_arg_types(t), sizeof(t), __alignof__(t))))
|
||||
#define __builtin_va_copy(dest, src) (*(dest) = *(src))
|
||||
|
||||
#else /* _WIN64 */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_arg(ap, t) ((sizeof(t) > 8 || (sizeof(t) & (sizeof(t) - 1))) \
|
||||
? **(t **)((ap += 8) - 8) : *(t *)((ap += 8) - 8))
|
||||
#endif
|
||||
|
||||
#elif defined __arm__
|
||||
typedef char *__builtin_va_list;
|
||||
#define _tcc_alignof(type) ((int)&((struct {char c;type x;} *)0)->x)
|
||||
#define _tcc_align(addr,type) (((unsigned)addr + _tcc_alignof(type) - 1) \
|
||||
& ~(_tcc_alignof(type) - 1))
|
||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||
#define __builtin_va_arg(ap,type) (ap = (void *) ((_tcc_align(ap,type)+sizeof(type)+3) \
|
||||
&~3), *(type *)(ap - ((sizeof(type)+3)&~3)))
|
||||
|
||||
#elif defined __aarch64__
|
||||
#if defined __APPLE__
|
||||
typedef struct {
|
||||
void *__stack;
|
||||
} __builtin_va_list;
|
||||
|
||||
#else
|
||||
typedef struct {
|
||||
void *__stack, *__gr_top, *__vr_top;
|
||||
int __gr_offs, __vr_offs;
|
||||
} __builtin_va_list;
|
||||
|
||||
#endif
|
||||
#elif defined __riscv
|
||||
typedef char *__builtin_va_list;
|
||||
#define __va_reg_size (__riscv_xlen >> 3)
|
||||
#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
|
||||
& -(__alignof__(type)))
|
||||
#define __builtin_va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
|
||||
|
||||
#else /* __i386__ */
|
||||
typedef char *__builtin_va_list;
|
||||
#define __builtin_va_start(ap,last) (ap = ((char *)&(last)) + ((sizeof(last)+3)&~3))
|
||||
#define __builtin_va_arg(ap,t) (*(t*)((ap+=(sizeof(t)+3)&~3)-((sizeof(t)+3)&~3)))
|
||||
|
||||
#endif
|
||||
#define __builtin_va_end(ap) (void)(ap)
|
||||
#ifndef __builtin_va_copy
|
||||
# define __builtin_va_copy(dest, src) (dest) = (src)
|
||||
#endif
|
||||
|
||||
/* TCC BBUILTIN AND BOUNDS ALIASES */
|
||||
#ifdef __leading_underscore
|
||||
# define __RENAME(X) __asm__("_"X)
|
||||
#else
|
||||
# define __RENAME(X) __asm__(X)
|
||||
#endif
|
||||
|
||||
#ifdef __TCC_BCHECK__
|
||||
# define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME("__bound_"#name);
|
||||
# define __BOUND(ret,name,params) ret name params __RENAME("__bound_"#name);
|
||||
#else
|
||||
# define __BUILTINBC(ret,name,params) ret __builtin_##name params __RENAME(#name);
|
||||
# define __BOUND(ret,name,params)
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
#define __BOTH __BOUND
|
||||
#define __BUILTIN(ret,name,params)
|
||||
#else
|
||||
#define __BOTH(ret,name,params) __BUILTINBC(ret,name,params)__BOUND(ret,name,params)
|
||||
#define __BUILTIN(ret,name,params) ret __builtin_##name params __RENAME(#name);
|
||||
#endif
|
||||
|
||||
__BOTH(void*, memcpy, (void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(void*, memmove, (void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(void*, memset, (void *, int, __SIZE_TYPE__))
|
||||
__BOTH(int, memcmp, (const void *, const void*, __SIZE_TYPE__))
|
||||
__BOTH(__SIZE_TYPE__, strlen, (const char *))
|
||||
__BOTH(char*, strcpy, (char *, const char *))
|
||||
__BOTH(char*, strncpy, (char *, const char*, __SIZE_TYPE__))
|
||||
__BOTH(int, strcmp, (const char*, const char*))
|
||||
__BOTH(int, strncmp, (const char*, const char*, __SIZE_TYPE__))
|
||||
__BOTH(char*, strcat, (char*, const char*))
|
||||
__BOTH(char*, strncat, (char*, const char*, __SIZE_TYPE__))
|
||||
__BOTH(char*, strchr, (const char*, int))
|
||||
__BOTH(char*, strrchr, (const char*, int))
|
||||
__BOTH(char*, strdup, (const char*))
|
||||
#if defined __ARM_EABI__
|
||||
__BOUND(void*,__aeabi_memcpy,(void*,const void*,__SIZE_TYPE__))
|
||||
__BOUND(void*,__aeabi_memmove,(void*,const void*,__SIZE_TYPE__))
|
||||
__BOUND(void*,__aeabi_memmove4,(void*,const void*,__SIZE_TYPE__))
|
||||
__BOUND(void*,__aeabi_memmove8,(void*,const void*,__SIZE_TYPE__))
|
||||
__BOUND(void*,__aeabi_memset,(void*,int,__SIZE_TYPE__))
|
||||
#endif
|
||||
|
||||
#if defined __linux__ || defined __APPLE__ // HAVE MALLOC_REDIR
|
||||
#define __MAYBE_REDIR __BUILTIN
|
||||
#else
|
||||
#define __MAYBE_REDIR __BOTH
|
||||
#endif
|
||||
__MAYBE_REDIR(void*, malloc, (__SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, realloc, (void *, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, calloc, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void*, memalign, (__SIZE_TYPE__, __SIZE_TYPE__))
|
||||
__MAYBE_REDIR(void, free, (void*))
|
||||
#if defined __i386__ || defined __x86_64__
|
||||
__BOTH(void*, alloca, (__SIZE_TYPE__))
|
||||
#else
|
||||
__BUILTIN(void*, alloca, (__SIZE_TYPE__))
|
||||
#endif
|
||||
__BUILTIN(void, abort, (void))
|
||||
__BOUND(void, longjmp, ())
|
||||
#if !defined _WIN32
|
||||
__BOUND(void*, mmap, ())
|
||||
__BOUND(int, munmap, ())
|
||||
#endif
|
||||
#undef __BUILTINBC
|
||||
#undef __BUILTIN
|
||||
#undef __BOUND
|
||||
#undef __BOTH
|
||||
#undef __MAYBE_REDIR
|
||||
#undef __RENAME
|
||||
|
||||
#define __BUILTIN_EXTERN(name,u) \
|
||||
int __builtin_##name(u int); \
|
||||
int __builtin_##name##l(u long); \
|
||||
int __builtin_##name##ll(u long long);
|
||||
__BUILTIN_EXTERN(ffs,)
|
||||
__BUILTIN_EXTERN(clz, unsigned)
|
||||
__BUILTIN_EXTERN(ctz, unsigned)
|
||||
__BUILTIN_EXTERN(clrsb,)
|
||||
__BUILTIN_EXTERN(popcount, unsigned)
|
||||
__BUILTIN_EXTERN(parity, unsigned)
|
||||
#undef __BUILTIN_EXTERN
|
||||
|
||||
#endif /* ndef __TCC_PP__ */
|
80
lib/tcc/include/tcclib.h
Normal file
80
lib/tcc/include/tcclib.h
Normal file
|
@ -0,0 +1,80 @@
|
|||
/* Simple libc header for TCC
|
||||
*
|
||||
* Add any function you want from the libc there. This file is here
|
||||
* only for your convenience so that you do not need to put the whole
|
||||
* glibc include files on your floppy disk
|
||||
*/
|
||||
#ifndef _TCCLIB_H
|
||||
#define _TCCLIB_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
/* stdlib.h */
|
||||
void *calloc(size_t nmemb, size_t size);
|
||||
void *malloc(size_t size);
|
||||
void free(void *ptr);
|
||||
void *realloc(void *ptr, size_t size);
|
||||
int atoi(const char *nptr);
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
void exit(int);
|
||||
|
||||
/* stdio.h */
|
||||
typedef struct __FILE FILE;
|
||||
#define EOF (-1)
|
||||
extern FILE *stdin;
|
||||
extern FILE *stdout;
|
||||
extern FILE *stderr;
|
||||
FILE *fopen(const char *path, const char *mode);
|
||||
FILE *fdopen(int fildes, const char *mode);
|
||||
FILE *freopen(const char *path, const char *mode, FILE *stream);
|
||||
int fclose(FILE *stream);
|
||||
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
size_t fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream);
|
||||
int fgetc(FILE *stream);
|
||||
char *fgets(char *s, int size, FILE *stream);
|
||||
int getc(FILE *stream);
|
||||
int getchar(void);
|
||||
char *gets(char *s);
|
||||
int ungetc(int c, FILE *stream);
|
||||
int fflush(FILE *stream);
|
||||
int putchar (int c);
|
||||
|
||||
int printf(const char *format, ...);
|
||||
int fprintf(FILE *stream, const char *format, ...);
|
||||
int sprintf(char *str, const char *format, ...);
|
||||
int snprintf(char *str, size_t size, const char *format, ...);
|
||||
int asprintf(char **strp, const char *format, ...);
|
||||
int dprintf(int fd, const char *format, ...);
|
||||
int vprintf(const char *format, va_list ap);
|
||||
int vfprintf(FILE *stream, const char *format, va_list ap);
|
||||
int vsprintf(char *str, const char *format, va_list ap);
|
||||
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
|
||||
int vasprintf(char **strp, const char *format, va_list ap);
|
||||
int vdprintf(int fd, const char *format, va_list ap);
|
||||
|
||||
void perror(const char *s);
|
||||
|
||||
/* string.h */
|
||||
char *strcat(char *dest, const char *src);
|
||||
char *strchr(const char *s, int c);
|
||||
char *strrchr(const char *s, int c);
|
||||
char *strcpy(char *dest, const char *src);
|
||||
void *memcpy(void *dest, const void *src, size_t n);
|
||||
void *memmove(void *dest, const void *src, size_t n);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
char *strdup(const char *s);
|
||||
size_t strlen(const char *s);
|
||||
|
||||
/* dlfcn.h */
|
||||
#define RTLD_LAZY 0x001
|
||||
#define RTLD_NOW 0x002
|
||||
#define RTLD_GLOBAL 0x100
|
||||
|
||||
void *dlopen(const char *filename, int flag);
|
||||
const char *dlerror(void);
|
||||
void *dlsym(void *handle, char *symbol);
|
||||
int dlclose(void *handle);
|
||||
|
||||
#endif /* _TCCLIB_H */
|
89
lib/tcc/include/tgmath.h
Normal file
89
lib/tcc/include/tgmath.h
Normal file
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* ISO C Standard: 7.22 Type-generic math <tgmath.h>
|
||||
*/
|
||||
|
||||
#ifndef _TGMATH_H
|
||||
#define _TGMATH_H
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#ifndef __cplusplus
|
||||
#define __tgmath_real(x, F) \
|
||||
_Generic ((x), float: F##f, long double: F##l, default: F)(x)
|
||||
#define __tgmath_real_2_1(x, y, F) \
|
||||
_Generic ((x), float: F##f, long double: F##l, default: F)(x, y)
|
||||
#define __tgmath_real_2(x, y, F) \
|
||||
_Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y)
|
||||
#define __tgmath_real_3_2(x, y, z, F) \
|
||||
_Generic ((x)+(y), float: F##f, long double: F##l, default: F)(x, y, z)
|
||||
#define __tgmath_real_3(x, y, z, F) \
|
||||
_Generic ((x)+(y)+(z), float: F##f, long double: F##l, default: F)(x, y, z)
|
||||
|
||||
/* Functions defined in both <math.h> and <complex.h> (7.22p4) */
|
||||
#define acos(z) __tgmath_real(z, acos)
|
||||
#define asin(z) __tgmath_real(z, asin)
|
||||
#define atan(z) __tgmath_real(z, atan)
|
||||
#define acosh(z) __tgmath_real(z, acosh)
|
||||
#define asinh(z) __tgmath_real(z, asinh)
|
||||
#define atanh(z) __tgmath_real(z, atanh)
|
||||
#define cos(z) __tgmath_real(z, cos)
|
||||
#define sin(z) __tgmath_real(z, sin)
|
||||
#define tan(z) __tgmath_real(z, tan)
|
||||
#define cosh(z) __tgmath_real(z, cosh)
|
||||
#define sinh(z) __tgmath_real(z, sinh)
|
||||
#define tanh(z) __tgmath_real(z, tanh)
|
||||
#define exp(z) __tgmath_real(z, exp)
|
||||
#define log(z) __tgmath_real(z, log)
|
||||
#define pow(z1,z2) __tgmath_real_2(z1, z2, pow)
|
||||
#define sqrt(z) __tgmath_real(z, sqrt)
|
||||
#define fabs(z) __tgmath_real(z, fabs)
|
||||
|
||||
/* Functions defined in <math.h> only (7.22p5) */
|
||||
#define atan2(x,y) __tgmath_real_2(x, y, atan2)
|
||||
#define cbrt(x) __tgmath_real(x, cbrt)
|
||||
#define ceil(x) __tgmath_real(x, ceil)
|
||||
#define copysign(x,y) __tgmath_real_2(x, y, copysign)
|
||||
#define erf(x) __tgmath_real(x, erf)
|
||||
#define erfc(x) __tgmath_real(x, erfc)
|
||||
#define exp2(x) __tgmath_real(x, exp2)
|
||||
#define expm1(x) __tgmath_real(x, expm1)
|
||||
#define fdim(x,y) __tgmath_real_2(x, y, fdim)
|
||||
#define floor(x) __tgmath_real(x, floor)
|
||||
#define fma(x,y,z) __tgmath_real_3(x, y, z, fma)
|
||||
#define fmax(x,y) __tgmath_real_2(x, y, fmax)
|
||||
#define fmin(x,y) __tgmath_real_2(x, y, fmin)
|
||||
#define fmod(x,y) __tgmath_real_2(x, y, fmod)
|
||||
#define frexp(x,y) __tgmath_real_2_1(x, y, frexp)
|
||||
#define hypot(x,y) __tgmath_real_2(x, y, hypot)
|
||||
#define ilogb(x) __tgmath_real(x, ilogb)
|
||||
#define ldexp(x,y) __tgmath_real_2_1(x, y, ldexp)
|
||||
#define lgamma(x) __tgmath_real(x, lgamma)
|
||||
#define llrint(x) __tgmath_real(x, llrint)
|
||||
#define llround(x) __tgmath_real(x, llround)
|
||||
#define log10(x) __tgmath_real(x, log10)
|
||||
#define log1p(x) __tgmath_real(x, log1p)
|
||||
#define log2(x) __tgmath_real(x, log2)
|
||||
#define logb(x) __tgmath_real(x, logb)
|
||||
#define lrint(x) __tgmath_real(x, lrint)
|
||||
#define lround(x) __tgmath_real(x, lround)
|
||||
#define nearbyint(x) __tgmath_real(x, nearbyint)
|
||||
#define nextafter(x,y) __tgmath_real_2(x, y, nextafter)
|
||||
#define nexttoward(x,y) __tgmath_real_2(x, y, nexttoward)
|
||||
#define remainder(x,y) __tgmath_real_2(x, y, remainder)
|
||||
#define remquo(x,y,z) __tgmath_real_3_2(x, y, z, remquo)
|
||||
#define rint(x) __tgmath_real(x, rint)
|
||||
#define round(x) __tgmath_real(x, round)
|
||||
#define scalbln(x,y) __tgmath_real_2_1(x, y, scalbln)
|
||||
#define scalbn(x,y) __tgmath_real_2_1(x, y, scalbn)
|
||||
#define tgamma(x) __tgmath_real(x, tgamma)
|
||||
#define trunc(x) __tgmath_real(x, trunc)
|
||||
|
||||
/* Functions defined in <complex.h> only (7.22p6)
|
||||
#define carg(z) __tgmath_cplx_only(z, carg)
|
||||
#define cimag(z) __tgmath_cplx_only(z, cimag)
|
||||
#define conj(z) __tgmath_cplx_only(z, conj)
|
||||
#define cproj(z) __tgmath_cplx_only(z, cproj)
|
||||
#define creal(z) __tgmath_cplx_only(z, creal)
|
||||
*/
|
||||
#endif /* __cplusplus */
|
||||
#endif /* _TGMATH_H */
|
12
lib/tcc/include/varargs.h
Normal file
12
lib/tcc/include/varargs.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
/**
|
||||
* This file has no copyright assigned and is placed in the Public Domain.
|
||||
* This file is part of the w64 mingw-runtime package.
|
||||
* No warranty is given; refer to the file DISCLAIMER within this package.
|
||||
*/
|
||||
#ifndef _VARARGS_H
|
||||
#define _VARARGS_H
|
||||
|
||||
#error "TinyCC no longer implements <varargs.h>."
|
||||
#error "Revise your code to use <stdarg.h>."
|
||||
|
||||
#endif
|
BIN
lib/tcc/libtcc1.a
Normal file
BIN
lib/tcc/libtcc1.a
Normal file
Binary file not shown.
26
runtime/runtime.c
Normal file
26
runtime/runtime.c
Normal file
|
@ -0,0 +1,26 @@
|
|||
#include "runtime.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
|
||||
int subtract(int a, int b) {
|
||||
return a - b;
|
||||
}
|
||||
|
||||
int divide(int a, int b) {
|
||||
return a / b;
|
||||
}
|
||||
|
||||
int multiply(int a, int b) {
|
||||
return a * b;
|
||||
}
|
||||
|
||||
void print_str(const char* s) {
|
||||
printf("%s\n", s);
|
||||
}
|
||||
|
||||
void print_num(int n) {
|
||||
printf("%d\n", n);
|
||||
}
|
12
runtime/runtime.h
Normal file
12
runtime/runtime.h
Normal file
|
@ -0,0 +1,12 @@
|
|||
#ifndef __RUNTIME_H__
|
||||
#define __RUNTIME_H__
|
||||
|
||||
int add(int a, int b);
|
||||
int subtract(int a, int b);
|
||||
int divide(int a, int b);
|
||||
int multiply(int a, int b);
|
||||
|
||||
void print_str(const char* s);
|
||||
void print_num(int n);
|
||||
|
||||
#endif
|
131
src/ast.c
Normal file
131
src/ast.c
Normal file
|
@ -0,0 +1,131 @@
|
|||
#include <ast.h>
|
||||
|
||||
const char* ASTTypeText[] = {
|
||||
"Program",
|
||||
"CallExpression",
|
||||
"NumberLiteral",
|
||||
"StringLiteral"
|
||||
};
|
||||
|
||||
ASTNode* ast_parse(Token** token) {
|
||||
ASTVec body = { 0 };
|
||||
|
||||
while((*token) != NULL) {
|
||||
sl_vec_push(body, ast_walk(token));
|
||||
}
|
||||
|
||||
return ast_create_program(body);
|
||||
}
|
||||
|
||||
ASTNode* ast_walk(Token** token) {
|
||||
if((*token)->type == TOKEN_NUMBER) {
|
||||
ASTNode* number = ast_create_number_literal((*token)->value);
|
||||
ast_step(token);
|
||||
return number;
|
||||
}
|
||||
|
||||
if((*token)->type == TOKEN_STRING) {
|
||||
ASTNode* string = ast_create_string_literal((*token)->value);
|
||||
ast_step(token);
|
||||
return string;
|
||||
}
|
||||
|
||||
if((*token)->type == TOKEN_LPAREN) { // Call expression
|
||||
ast_step(token);
|
||||
const char* name = (*token)->value;
|
||||
ASTVec params = { 0 };
|
||||
|
||||
ast_step(token);
|
||||
|
||||
while((*token)->type != TOKEN_RPAREN) {
|
||||
sl_vec_push(params, ast_walk(token));
|
||||
}
|
||||
|
||||
ast_step(token);
|
||||
|
||||
return ast_create_call_expression(name, params);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void ast_step(Token** token) {
|
||||
(*token) = (*token)->next;
|
||||
}
|
||||
|
||||
char* gen_ident(int indent) {
|
||||
char* text = malloc(sizeof(char) * (indent + 1));
|
||||
memset(text, ' ', indent);
|
||||
text[indent] = '\0';
|
||||
return text;
|
||||
}
|
||||
|
||||
void ast_print(ASTNode* node, int indent) {
|
||||
switch(node->type) {
|
||||
case AST_PROGRAM:
|
||||
printf("%s%s\n%sBody:\n",
|
||||
gen_ident(indent), ASTTypeText[node->type],
|
||||
gen_ident(indent + 2));
|
||||
|
||||
indent += 2;
|
||||
for(sl_vec_it(n, node->body)) {
|
||||
ast_print(*n, indent + 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case AST_CALL_EXPRESSION:
|
||||
printf("%s%s\n%sName: %s\n%sParams:\n",
|
||||
gen_ident(indent), ASTTypeText[node->type],
|
||||
gen_ident(indent + 2), node->name,
|
||||
gen_ident(indent + 2));
|
||||
|
||||
indent += 2;
|
||||
for(sl_vec_it(n, node->params)) {
|
||||
ast_print(*n, indent + 2);
|
||||
}
|
||||
break;
|
||||
|
||||
case AST_NUMBER_LITERAL:
|
||||
printf("%s%s\n%sValue: %s\n",
|
||||
gen_ident(indent), ASTTypeText[node->type],
|
||||
gen_ident(indent + 2), node->value);
|
||||
break;
|
||||
|
||||
case AST_STRING_LITERAL:
|
||||
printf("%s%s\n%sValue: %s\n",
|
||||
gen_ident(indent), ASTTypeText[node->type],
|
||||
gen_ident(indent + 2), node->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ASTNode* ast_create_empty(ASTType type) {
|
||||
ASTNode* new_node = malloc(sizeof(ASTNode));
|
||||
new_node->type = type;
|
||||
return new_node;
|
||||
}
|
||||
|
||||
ASTNode* ast_create_program(ASTVec body) {
|
||||
ASTNode* node = ast_create_empty(AST_PROGRAM);
|
||||
node->body = body;
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode* ast_create_call_expression(const char* name, ASTVec params) {
|
||||
ASTNode* node = ast_create_empty(AST_CALL_EXPRESSION);
|
||||
node->name = name;
|
||||
node->params = params;
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode* ast_create_number_literal(const char* value) {
|
||||
ASTNode* node = ast_create_empty(AST_NUMBER_LITERAL);
|
||||
node->value = value;
|
||||
return node;
|
||||
}
|
||||
|
||||
ASTNode* ast_create_string_literal(const char* value) {
|
||||
ASTNode* node = ast_create_empty(AST_STRING_LITERAL);
|
||||
node->value = value;
|
||||
return node;
|
||||
}
|
40
src/codegen.c
Normal file
40
src/codegen.c
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <codegen.h>
|
||||
#include <slibs/slibs.h>
|
||||
|
||||
const char* codegen(ASTNode* node) {
|
||||
if(node->type == AST_PROGRAM) {
|
||||
sl_string code = sl_string("#include <runtime.h>\n\nint main() {\n");
|
||||
for(sl_vec_it(n, node->body)) {
|
||||
sl_append_c_str(&code, codegen(*n));
|
||||
sl_append_c_str(&code, ";\n");
|
||||
}
|
||||
sl_append_c_str(&code, "}");
|
||||
return sl_c_str(code);
|
||||
}
|
||||
|
||||
if(node->type == AST_CALL_EXPRESSION) {
|
||||
sl_string code = sl_string(node->name);
|
||||
sl_append_c_str(&code, "(");
|
||||
for(size_t i = 0; i < node->params.size; i++) {
|
||||
sl_append_c_str(&code, codegen(node->params.data[i]));
|
||||
if(i < node->params.size - 1) {
|
||||
sl_append_c_str(&code, ", ");
|
||||
}
|
||||
}
|
||||
sl_append_c_str(&code, ")");
|
||||
return sl_c_str(code);
|
||||
}
|
||||
|
||||
if(node->type == AST_NUMBER_LITERAL) {
|
||||
return node->value;
|
||||
}
|
||||
|
||||
if(node->type == AST_STRING_LITERAL) {
|
||||
sl_string code = sl_string("\"");
|
||||
sl_append_c_str(&code, node->value);
|
||||
sl_append_c_str(&code, "\"");
|
||||
return sl_c_str(code);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
41
src/main.c
Normal file
41
src/main.c
Normal file
|
@ -0,0 +1,41 @@
|
|||
#define SL_IMPLEMENTATION
|
||||
#include <slibs/slibs.h>
|
||||
#include <tokenizer.h>
|
||||
#include <ast.h>
|
||||
#include <codegen.h>
|
||||
#include <tcc/libtcc.h>
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
assert(argc > 2);
|
||||
|
||||
sl_string buffer = { 0 };
|
||||
sl_read_file(argv[1], &buffer);
|
||||
|
||||
Token* root = tokenize(sl_c_str(buffer));
|
||||
printf("Tokens:\n");
|
||||
Token* curr = root;
|
||||
while(curr != NULL) {
|
||||
printf("%s: %s\n", TokenTypeText[curr->type], curr->value);
|
||||
curr = curr->next;
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("AST:\n");
|
||||
ASTNode* program = ast_parse(&root);
|
||||
ast_print(program, 0);
|
||||
printf("\n");
|
||||
|
||||
printf("Codegen:\n");
|
||||
const char* code = codegen(program);
|
||||
printf("%s\n\n", code);
|
||||
|
||||
TCCState* state = tcc_new();
|
||||
assert(tcc_set_output_type(state, TCC_OUTPUT_EXE) == 0);
|
||||
tcc_set_lib_path(state, "lib/tcc");
|
||||
assert(tcc_add_include_path(state, "runtime") == 0);
|
||||
assert(tcc_add_file(state, "runtime/runtime.c") == 0);
|
||||
assert(tcc_compile_string(state, code) == 0);
|
||||
assert(tcc_output_file(state, argv[2]) == 0);
|
||||
|
||||
printf("Binary produced: %s\n", argv[2]);
|
||||
}
|
69
src/regexp.c
Normal file
69
src/regexp.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <regexp.h>
|
||||
|
||||
void regex_step(char** input, char* c) {
|
||||
(*input)++;
|
||||
*c = **input;
|
||||
}
|
||||
|
||||
regex_t regex_create(const char* pattern, int flags) {
|
||||
regex_t regex;
|
||||
int ret = regcomp(®ex, pattern, flags);
|
||||
if(ret) {
|
||||
char msgbuf[100];
|
||||
regerror(ret, ®ex, msgbuf, sizeof(msgbuf));
|
||||
fprintf(stderr, "Regex compilation failed: %s\n", msgbuf);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
return regex;
|
||||
}
|
||||
|
||||
int match_char(regex_t regex, char c) {
|
||||
return regnexec(®ex, &c, 1, 0, NULL, 0) != REG_NOMATCH;
|
||||
}
|
||||
|
||||
sl_string collect_until(match_func matcher, regex_t regex, char** input) {
|
||||
sl_string collected = {0};
|
||||
char c = **input;
|
||||
|
||||
while (matcher(regex, c, input)) {
|
||||
sl_vec_push(collected, c);
|
||||
regex_step(input, &c);
|
||||
}
|
||||
|
||||
return collected;
|
||||
}
|
||||
|
||||
int not_match_char(regex_t regex, char c, char** _) {
|
||||
return !match_char(regex, c);
|
||||
}
|
||||
|
||||
int match_char_matcher(regex_t regex, char c, char** _) {
|
||||
return match_char(regex, c);
|
||||
}
|
||||
|
||||
int not_match_char_escapable(regex_t regex, char c, char** input) {
|
||||
return !match_char(regex, c) || *((*input) - 1) == '\\';
|
||||
}
|
||||
|
||||
int match_char_escapable(regex_t regex, char c, char** input) {
|
||||
return match_char(regex, c) || *(*input) == '\\';
|
||||
}
|
||||
|
||||
sl_string collect_until_match(regex_t regex, char** input) {
|
||||
return collect_until(not_match_char, regex, input);
|
||||
}
|
||||
|
||||
sl_string collect_until_no_match(regex_t regex, char** input) {
|
||||
return collect_until(match_char_matcher, regex, input);
|
||||
}
|
||||
|
||||
sl_string collect_until_match_escapable(regex_t regex, char** input) {
|
||||
return collect_until(not_match_char_escapable, regex, input);
|
||||
}
|
||||
|
||||
sl_string collect_until_no_match_escapable(regex_t regex, char** input) {
|
||||
return collect_until(match_char_escapable, regex, input);
|
||||
}
|
77
src/tokenizer.c
Normal file
77
src/tokenizer.c
Normal file
|
@ -0,0 +1,77 @@
|
|||
#include <stdio.h>
|
||||
#include <regex.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <regexp.h>
|
||||
#include <tokenizer.h>
|
||||
#include <slibs/slibs.h>
|
||||
|
||||
const char* TokenTypeText[] = {
|
||||
"l_paren",
|
||||
"r_paren",
|
||||
"number",
|
||||
"name",
|
||||
"string"
|
||||
};
|
||||
|
||||
Token* tokenize(char* input) {
|
||||
regex_t name = regex_create("[a-z_]", REG_ICASE);
|
||||
regex_t number = regex_create("[0-9]", 0);
|
||||
regex_t string = regex_create("\"", 0);
|
||||
regex_t whitespace = regex_create("[ \n]", 0);
|
||||
Token* root = NULL;
|
||||
sl_string collected = {0};
|
||||
|
||||
char c = *input;
|
||||
while (c != '\0') {
|
||||
if (match_char(name, c)) {
|
||||
collected = collect_until_no_match(name, &input);
|
||||
root = token_create(sl_c_str(collected), TOKEN_NAME, root);
|
||||
} else if (match_char(number, c)) {
|
||||
collected = collect_until_no_match(number, &input);
|
||||
root = token_create(sl_c_str(collected), TOKEN_NUMBER, root);
|
||||
} else if (c == '(') {
|
||||
root = token_create("(", TOKEN_LPAREN, root);
|
||||
input++;
|
||||
} else if (c == ')') {
|
||||
root = token_create(")", TOKEN_RPAREN, root);
|
||||
input++;
|
||||
} else if (match_char(whitespace, c)) {
|
||||
input++;
|
||||
} else if (match_char(string, c)) {
|
||||
regex_step(&input, &c);
|
||||
collected = collect_until_match_escapable(string, &input);
|
||||
root = token_create(sl_c_str(collected), TOKEN_STRING, root);
|
||||
input++;
|
||||
} else {
|
||||
printf("%c: no match\n", c);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
c = *input;
|
||||
}
|
||||
|
||||
regfree(&name);
|
||||
regfree(&number);
|
||||
regfree(&string);
|
||||
regfree(&whitespace);
|
||||
return root;
|
||||
}
|
||||
|
||||
Token* token_create(char* value, TokenType type, Token* root) {
|
||||
Token* new_token = malloc(sizeof(Token));
|
||||
new_token->value = value;
|
||||
new_token->type = type;
|
||||
|
||||
return token_append(root, new_token);;
|
||||
}
|
||||
|
||||
Token* token_append(Token* root, Token* new_token) {
|
||||
if (!root) return new_token;
|
||||
Token* current = root;
|
||||
while (current->next) {
|
||||
current = current->next;
|
||||
}
|
||||
current->next = new_token;
|
||||
return root;
|
||||
}
|
Loading…
Add table
Reference in a new issue