From 967be9e750221ab2ab783f95df79bb26d290a45e Mon Sep 17 00:00:00 2001 From: Martial Simon Date: Mon, 15 Sep 2025 01:07:58 +0200 Subject: add: added projects --- tiger-compiler/src/llvmtranslate/tiger-runtime.c | 304 +++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 tiger-compiler/src/llvmtranslate/tiger-runtime.c (limited to 'tiger-compiler/src/llvmtranslate/tiger-runtime.c') diff --git a/tiger-compiler/src/llvmtranslate/tiger-runtime.c b/tiger-compiler/src/llvmtranslate/tiger-runtime.c new file mode 100644 index 0000000..f952e0f --- /dev/null +++ b/tiger-compiler/src/llvmtranslate/tiger-runtime.c @@ -0,0 +1,304 @@ +/** + \file llvm/tiger-runtime.c + \brief C Implementation of the Tiger runtime. +*/ + +#include +#include +#include +#include +#include + +#define EXIT_RUNTIME_FAILURE 120 + +// FWD, declared by tc +void tc_main(int); + +/** \name Internal functions (calls generated by the compiler only). */ +/** \{ */ + +/** \brief Allocate an array and fill it with a default value. + \param size The size of the array. + \param elt The default element. + + An element size is always the size of a word on 32-bit systems. +*/ +int *tc_init_array(int size, int elt) +{ + int *arr = (int *)malloc(size * sizeof (elt)); + for (size_t i = 0; i < size; ++i) + arr[i] = elt; + return arr; +} +/** \} */ + +/** \name Miscellaneous */ +/** \{ */ + +/** \brief Equivalent to operator! in C. + \param i The integer to be inversed. +*/ +int tc_not(int i) +{ + return !i; +} + +/** \brief Exit the program with the desired status. + \param status The status code. +*/ +void tc_exit(int status) +{ + exit(status); +} +/** \} */ + +/** \name Operations on strings. */ +/** \{ */ + +// Small trick. Add a \0 after each char in the consts +// This is filled in tc_main +static char consts[512] = { 0 }; + +/** \brief Get a string containing the character represented by the ascii value + * of \a i. + \param i The ascii value of the desired character. +*/ +const char *tc_chr(int i) +{ + if (!(0 <= i && i <= 255)) + { + fputs("chr: character out of range\n", stderr); + exit(EXIT_RUNTIME_FAILURE); + } + return consts + i * 2; +} + +/** \brief Concatenate two strings. + \param a The first string. + \param b The second string. +*/ +const char *tc_concat(const char *a, const char *b) +{ + size_t len_a = strlen(a); + size_t len_b = strlen(b); + if (len_a == 0) + return b; + else if (len_b == 0) + return a; + else + { + int i = 0; + int n = len_a + len_b; + char *t = (char *) malloc(n + 1); + for (i = 0; i < len_a; i++) + t[i] = a[i]; + for (i = 0; i < len_b; i++) + t[i + len_a] = b[i]; + t[n] = '\0'; + return t; + } +} + +/** \brief Get the ascii value of a character. + \param s The string representing the desired character to be converted. + + Inverse of `tc_chr`. +*/ +int tc_ord(const char *s) +{ + size_t len = strlen(s); + if (len == 0) + return -1; + else + return s[0]; +} + +/** \brief Get the size of a string. + \param s The string. +*/ +int tc_size(const char *s) +{ + return strlen(s); +} + +/** \brief Return a part of the string \a s. + \param s The source string + \param first The first character of the extraction (starting at 0) + \param n The number of characters to get. + + \a first and \a n must be positive, and one shall not go beyond the size + of \a s. Otherwise, exit with runtime failure. +*/ +const char *tc_substring(const char *s, int first, int n) +{ + size_t len = strlen(s); + if (!(0 <= first + && 0 <= n + && first + n <= len)) + { + fputs("substring: arguments out of bounds\n", stderr); + exit(EXIT_RUNTIME_FAILURE); + } + + if (n == 1) + return consts + s[first] * 2; + else + { + char *t = (char *) malloc(n + 1); + for (int i = 0; i < n; i++) + t[i] = s[first + i]; + t[n] = '\0'; + return t; + } +} + +/** \brief Compare two strings. + \param lhs The first string. + \param rhs The second string. +*/ +int tc_strcmp(const char *lhs, const char *rhs) +{ + return strcmp(lhs, rhs); +} + +/** \brief Return a part of the string \a s. + \param s The source string + \param first The first character of the extraction (starting at 0) + \param n The number of characters to get. + + \a first and \a n must be positive, and one shall not go beyond the size + of \a s. Otherwise, exit with runtime failure. +*/ +int tc_streq(const char *lhs, const char *rhs) +{ + return strcmp(lhs, rhs) == 0; +} +/** \} */ + +/** \name Input/Output. */ +/** \{ */ + +/** \brief Get a character from the standard input. +*/ +const char *tc_getchar() +{ + int i = getc(stdin); + if (i == EOF) + return ""; + else + return consts + i * 2; +} + +/** \brief Print a string on the standard output. + \param s The string to be printed. +*/ +void tc_print(const char *s) +{ + printf("%s", s); +} + +/** \brief Print a string on the standard error. + \param s The string to be printed. +*/ +void tc_print_err(const char *s) +{ + fprintf(stderr, "%s", s); +} + +/** \brief Print an int on the standard error. + \param i The int to be printed. +*/ +void tc_print_int(int i) +{ + printf("%d", i); +} + +/** \brief Flush the standard output. +*/ +void tc_flush() +{ + fflush(stdout); +} + +/** \} */ + +/** \name Custom primitives. */ +/** \{ */ + +/** \brief Terminate the program with an error if condition if false + \param condition Condition to assert, represented as a Tiger 32 bits integer + \param instruction_str The condition represented as a string, used for + pretty-printing. Can be NULL + \param filename File in which the assertion comes from. Can be NULL +*/ +void tc_assertion(const int condition, const char* instruction_str, + const char* filename) +{ + if (condition) + { + return; + } + + if (instruction_str == NULL) + { + instruction_str = ""; + } + + if (filename == NULL) + { + filename = ""; + } + + fprintf(stderr, "%s: %s assertion is false. aborting\n", filename, + instruction_str); + abort(); +} + +/** + * \brief Proceed to a fork syscall and return the resulting process id. + * \return the resulting pid for the parent, 0 for the child, or -1 if the + * process forking failed + */ +int tc_fork() + { + return fork(); + } + +/** + * \brief Wait for the process specified by the provided id to end and return + * the resulting status code. + * \param pid a process, referenced by its identifier + * \return the process' status code + */ +int tc_wait_pid(int pid) + { + int status_code = -1; + waitpid(pid, &status_code, WUNTRACED | WCONTINUED); + return status_code; + } + +/** + * \brief Determine the exit code specified by a status code and return it. + * \param status_code any process status code + * \return the implied exit code + */ +int tc_get_exit_code(int status_code) + { + return WEXITSTATUS(status_code); + } + +/** \} */ + +int main() +{ + // Fill the `consts` array with every character in the ascii table, followed + // by a null character. + for (int i = 0; i < 512; i += 2) + { + consts[i] = i / 2; + consts[i + 1] = 0; + } + + tc_main(0); + return 0; +} -- cgit v1.2.3