Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,34 @@ jobs:
make check-sanitizer || exit 1
make check || exit 1

preprocessor-host:
runs-on: ubuntu-24.04
strategy:
matrix:
compiler: [gcc, clang]
architecture: [arm, riscv]
Comment on lines +59 to +64
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you create a new target?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea would be testing preprocessing produces correct output without interfering with the original target, which has additional checks to be performed such as sanitized build, IR regression test, and such.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the C preprocessor fails, there is no need to validate the C compiler itself.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, stripping out stage 2 building tasks should be enough?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly, stripping out stage 2 building tasks should be enough?

It fairly makes sense.

steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download dependencies
run: |
sudo apt-get update -q -y
sudo apt-get install -q -y graphviz jq
sudo apt-get install -q -y qemu-user
sudo apt-get install -q -y build-essential
- name: Configurate config
run: |
make distclean config ARCH=${{ matrix.architecture }}
- name: Preprocess stage 1 source code
env:
CC: ${{ matrix.compiler }}
run: |
make out/shecc
./out/shecc -E src/main.c > ./out/out.c
- name: Build stage 1 artifact
run: |
./out/shecc --no-libc -o out/shecc-stage1.elf ./out/out.c

coding-style:
runs-on: ubuntu-24.04
steps:
Expand Down
30 changes: 30 additions & 0 deletions lib/c.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@
#define INT_MAX 0x7fffffff
#define INT_MIN 0x80000000

#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2

#if defined(__arm__)
#define __SIZEOF_POINTER__ 4
#define __syscall_exit 1
#define __syscall_read 3
#define __syscall_write 4
#define __syscall_close 6
#define __syscall_open 5
#define __syscall_lseek 19
#define __syscall_mmap2 192
#define __syscall_munmap 91

Expand All @@ -34,6 +39,7 @@
#define __syscall_close 57
#define __syscall_open 1024
#define __syscall_openat 56
#define __syscall_lseek 62
#define __syscall_mmap2 222
#define __syscall_munmap 215

Expand Down Expand Up @@ -584,6 +590,30 @@ int fputc(int c, FILE *stream)
return c;
}

int fseek(FILE *stream, int offset, int whence)
{
#if defined(__arm__)
__syscall(__syscall_lseek, stream, offset, whence);
#elif defined(__riscv)
/* No need to offset */
__syscall(__syscall_lseek, stream, 0, offset, NULL, whence);
#endif
return 0;
Comment on lines +600 to +601
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handle the #else case in the same manner as ftell() does.

}

int ftell(FILE *stream)
{
#if defined(__arm__)
return __syscall(__syscall_lseek, stream, 0, SEEK_CUR);
#elif defined(__riscv)
int result;
__syscall(__syscall_lseek, stream, 0, 0, &result, SEEK_CUR);
return result;
#else
#error "Unsupported ftell support for current platform"
#endif
}

/* Non-portable: Assume page size is 4KiB */
#define PAGESIZE 4096

Expand Down
81 changes: 35 additions & 46 deletions src/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@

/* definitions */

#define DEBUG_BUILD false
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.


/* Common macro functions */
#define is_whitespace(c) (c == ' ' || c == '\t')
#define is_newline(c) (c == '\r' || c == '\n')
#define is_alnum(c) \
((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || \
(c >= '0' && c <= '9') || (c == '_'))
#define is_digit(c) ((c >= '0' && c <= '9'))
#define is_hex(c) \
(is_digit(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))

/* Limitations */
#define MAX_TOKEN_LEN 256
#define MAX_ID_LEN 64
Expand All @@ -26,14 +38,12 @@
#define MAX_BB_DOM_SUCC 64
#define MAX_BB_RDOM_SUCC 256
#define MAX_GLOBAL_IR 256
#define MAX_SOURCE 1048576
#define MAX_CODE 262144
#define MAX_DATA 262144
#define MAX_SYMTAB 65536
#define MAX_STRTAB 65536
#define MAX_HEADER 1024
#define MAX_SECTION 1024
#define MAX_ALIASES 128
#define MAX_CONSTANTS 1024
#define MAX_CASES 128
#define MAX_NESTING 128
Expand All @@ -46,7 +56,7 @@
#define SMALL_ARENA_SIZE 65536 /* 64 KiB - for small allocations */
#define LARGE_ARENA_SIZE 524288 /* 512 KiB - for instruction arena */
#define DEFAULT_FUNCS_SIZE 64
#define DEFAULT_INCLUSIONS_SIZE 16
#define DEFAULT_SRC_FILE_COUNT 8

/* Arena compaction bitmask flags for selective memory reclamation */
#define COMPACT_ARENA_BLOCK 0x01 /* BLOCK_ARENA - variables/blocks */
Expand Down Expand Up @@ -113,6 +123,7 @@ typedef struct {
/* lexer tokens */
typedef enum {
T_start, /* FIXME: Unused, intended for lexer state machine init */
T_eof, /* end-of-file (EOF) */
T_numeric,
T_identifier,
T_comma, /* , */
Expand Down Expand Up @@ -161,7 +172,6 @@ typedef enum {
T_question, /* ? */
T_colon, /* : */
T_semicolon, /* ; */
T_eof, /* end-of-file (EOF) */
T_ampersand, /* & */
T_return,
T_if,
Expand Down Expand Up @@ -193,38 +203,36 @@ typedef enum {
T_cppd_endif,
T_cppd_ifdef,
T_cppd_ifndef,
T_cppd_pragma
} token_t;
T_cppd_pragma,
/* C pre-processor specific, these kinds
* will be removed after pre-processing is done.
*/
T_newline,
T_backslash,
T_whitespace,
T_tab
} token_kind_t;

/* Source location tracking for better error reporting */
typedef struct {
int pos; /* raw source file position */
int len; /* length of token */
int line;
int column;
char *filename;
} source_location_t;

/* Token structure with metadata for enhanced lexing */
typedef struct token_info {
token_t type;
char value[MAX_TOKEN_LEN];
typedef struct token {
token_kind_t kind;
char *literal;
source_location_t location;
struct token_info *next; /* For freelist management */
} token_info_t;

/* Token freelist for memory reuse */
typedef struct {
token_info_t *freelist;
int allocated_count;
} token_pool_t;
struct token *next;
} token_t;

/* Token buffer for improved lookahead */
#define TOKEN_BUFFER_SIZE 8
typedef struct {
token_info_t *tokens[TOKEN_BUFFER_SIZE];
int head;
int tail;
int count;
} token_buffer_t;
typedef struct token_stream {
token_t *head;
token_t *tail;
} token_stream_t;

/* String pool for identifier deduplication */
typedef struct {
Expand Down Expand Up @@ -369,7 +377,7 @@ struct var {
int in_loop;
struct var *base;
int subscript;
struct var *subscripts[64];
struct var *subscripts[128];
int subscripts_idx;
rename_t rename;
ref_block_list_t ref_block_list; /* blocks which kill variable */
Expand All @@ -388,25 +396,13 @@ struct var {
int use_count; /* Number of times variable is used */
};

typedef struct {
char name[MAX_VAR_LEN];
bool is_variadic;
int start_source_idx;
var_t param_defs[MAX_PARAMS];
int num_param_defs;
int params[MAX_PARAMS];
int num_params;
bool disabled;
} macro_t;

typedef struct func func_t;

/* block definition */
struct block {
var_list_t locals;
struct block *parent;
func_t *func;
macro_t *macro;
struct block *next;
};

Expand Down Expand Up @@ -460,13 +456,6 @@ typedef struct {
type_t *type;
} lvalue_t;

/* alias for #defines */
typedef struct {
char alias[MAX_VAR_LEN];
char value[MAX_VAR_LEN];
bool disabled;
} alias_t;

/* constants for enums */
typedef struct {
char alias[MAX_VAR_LEN];
Expand Down
Loading