From 6cad09ec9c801e90d41f53ebcd673ef89050cc86 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Fri, 11 Feb 2022 17:41:33 +0100 Subject: Check if file to read is really a file --- README.md | 8 +++++++- doc/doc_extract.py | 2 +- executor/x86_64/asm.c | 6 +++--- optimize.md | 33 +++++++++++++++++++++++++++++++++ src/program.c | 6 ++++-- src/std/file.c | 28 +++++++++++++++------------- src/std/hash_map.c | 3 +++ tools/highlevel_c.py | 2 +- 8 files changed, 67 insertions(+), 21 deletions(-) create mode 100644 optimize.md diff --git a/README.md b/README.md index 4b12d62..fb2e44f 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Locks are only used in one place in the whole compilation stage, during @import # Dependencies Right now only the C standard library (C89) is required for a release build. In the future dependency on the C standard library might be removed and then amalgam would have 0 dependencies.\ -python2 is needed for tests to run additional code analyzis. +python3 is needed for tests to run additional code analyzis. # Limits Amalgam places limits on code for performance reasons. These are the limits: @@ -74,6 +74,12 @@ All branch targets should be 16-byte aligned. * Do not allow (re)assigning to variables in global scope. This wouldn't be consistent since files are parsed asynchronously so the order wouldn't be deterministic. * Compile error if a variable has the same name as a keyword. * Only allow importing files that has .amal extension, this also fixes the issue where windows has illegal filenames such as aux, nul, etc. Also do the same for the main file. +* Generate optimization report, where the code should be annotated with patterns the compiler sees and optimizes. This would help the user write code that the compiler can optimize. +* Handle a situation similar to this: https://github.com/ziglang/zig/issues/4021. +* Change the size of pthreads with setrlimit. +* Handle EINTR. +* Use semaphore instead of mutex to unlock other thread. +* Check redefinition of variables, parameters and member variables/functions. # Documents Documents are located under doc. The file doc/Documentation.md is generated from source files by running doc/doc_extract.py but there is no need to run this script unless you are modifying documentation in the source. diff --git a/doc/doc_extract.py b/doc/doc_extract.py index 3331ae0..16f7732 100755 --- a/doc/doc_extract.py +++ b/doc/doc_extract.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import sys import os diff --git a/executor/x86_64/asm.c b/executor/x86_64/asm.c index f57f117..718ebef 100644 --- a/executor/x86_64/asm.c +++ b/executor/x86_64/asm.c @@ -206,7 +206,7 @@ int asm_init(Asm *self) { amal_log_debug("asm: page size: %u", self->allocated_size); self->code = mmap(NULL, self->allocated_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(self->code == MAP_FAILED) - return -errno; + return -1; self->code_it = self->code; return 0; } @@ -253,7 +253,7 @@ typedef union { int asm_execute(Asm *self, u32 offset) { RawFuncCallPtr raw_func_ptr; if(mprotect(self->code, self->allocated_size, PROT_READ | PROT_EXEC) != 0) - return -errno; + return -1; /*asm_print_code_hex(self);*/ @@ -270,7 +270,7 @@ int asm_ensure_capacity(Asm *self, usize size) { usize new_size = self->allocated_size + am_pagesize(); void *new_mem = mmap(NULL, new_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); if(new_mem == MAP_FAILED) - return -errno; + return -1; am_memcpy(new_mem, self->code, self->allocated_size); munmap(self->code, self->allocated_size); diff --git a/optimize.md b/optimize.md new file mode 100644 index 0000000..b2418ef --- /dev/null +++ b/optimize.md @@ -0,0 +1,33 @@ +Turn ['a', 'i', 'u', 'e', 'o'].contains(c) into: + +1 - inline: +char arr[] = { 'a', 'i', 'u', 'e', 'o' }; +for(int i = 0; i < 5; ++i) { + if(arr[i] == c) + return true; +} +return false; + +2 - constant loop unrolling: +if('a' == c) + return true; +if('i' == c) + return true; +if('u' == c) + return true; +if('e' == c) + return true; +if('o' == c) + return true; +return false; + +3 - multiple comparisons to same variable turned into a switch: +switch(c) { + case 'a': + case 'i': + case 'u': + case 'e': + case 'o': + return true; +} +return false; diff --git a/src/program.c b/src/program.c index e53eb6b..e163b9b 100644 --- a/src/program.c +++ b/src/program.c @@ -871,12 +871,14 @@ int amal_program_save(amal_program *self, const char *filepath) { int err = 0; FILE *file = fopen(filepath, "wb"); if(!file) { - err = -errno; + perror(filepath); + err = -1; goto cleanup; } if(fwrite(self->data.data, 1, self->data.size, file) != self->data.size) { - err = -errno; + fprintf(stderr, "Failed to write %zu bytes to %s\n", self->data.size, filepath); + err = -1; goto cleanup; } diff --git a/src/std/file.c b/src/std/file.c index 4542aba..d486843 100644 --- a/src/std/file.c +++ b/src/std/file.c @@ -28,10 +28,8 @@ static int scan_dir_recursive_internal(char *dir_path, int path_length, scan_dir path_length_start = path_length; if((dir = opendir(dir_path)) == NULL) { - int error; - error = errno; amal_log_perror("scan_dir_recursive"); - return error; + return -1; } while((entry = readdir(dir)) != NULL) { @@ -178,9 +176,16 @@ int read_whole_file(const char *filepath, Buffer *data_result) { file = fopen(filepath, "rb"); if(!file) { - int error = errno; - amal_log_error("read_whole_file: %s failed, error: %s", filepath, strerror(error)); - return error; + amal_log_error("read_whole_file: %s failed, error: %s", filepath, strerror(errno)); + return -1; + } + + int fd = fileno(file); + struct stat s; + if(fstat(fd, &s) == -1 || !S_ISREG(s.st_mode)) { + amal_log_error("read_whole_file: %s failed, error: attempted to read a non-file", filepath); + fclose(file); + return -1; } result = fseek(file, 0, SEEK_END); @@ -191,9 +196,8 @@ int read_whole_file(const char *filepath, Buffer *data_result) { size = ftell(file); if(size == -1) { - int error = errno; - result = error; - amal_log_error("read_whole_file: %s failed, error: %s", filepath, strerror(error)); + result = -1; + amal_log_error("read_whole_file: %s failed, error: %s", filepath, strerror(errno)); goto cleanup; } @@ -223,10 +227,8 @@ int read_whole_file(const char *filepath, Buffer *data_result) { int file_get_canonical_path(const char *filepath, char **result_path, usize *result_path_size) { char result_path_tmp[PATH_MAX]; if(!realpath(filepath, result_path_tmp)) { - int ret; - ret = errno; - amal_log_error("file_get_canonical_path: realpath failed for path %s, error: %s", filepath, strerror(ret)); - return ret; + amal_log_error("file_get_canonical_path: realpath failed for path %s, error: %s", filepath, strerror(errno)); + return -1; } *result_path_size = strnlen(result_path_tmp, PATH_MAX); return_if_error(am_malloc(*result_path_size + 1, (void**)result_path)); diff --git a/src/std/hash_map.c b/src/std/hash_map.c index b4bd4c1..4bf55c6 100644 --- a/src/std/hash_map.c +++ b/src/std/hash_map.c @@ -224,6 +224,9 @@ bool hash_map_get_ref(HashMap *self, BufferView key, void **value) { HashMapBucketNode *bucket_node; bucket_size = buffer_get_size(&self->buckets, HashMapBucket); + if(bucket_size == 0) + return bool_false; + hash = self->hash_func((const u8*)key.data, key.size); bucket_index = hash % bucket_size; diff --git a/tools/highlevel_c.py b/tools/highlevel_c.py index b1c2dc3..cb75044 100755 --- a/tools/highlevel_c.py +++ b/tools/highlevel_c.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 import os import sys -- cgit v1.2.3