refactored standard library

This commit is contained in:
Sven Vogel 2024-08-11 18:40:20 +02:00
parent d01248ba25
commit cf59e9640d
34 changed files with 181 additions and 524 deletions

View File

@ -108,7 +108,19 @@ link_libraries(tomlc99)
# Standard library #
# ------------------------------------------------ #
add_subdirectory(lib)
# ------------------------------------------------ #
# LLD-C-Layer #
# ------------------------------------------------ #
add_subdirectory(dep/lldcl)
# Link lld libs and C++ LIBC
link_libraries(lldcl
lldCommon
lldCOFF
lldELF
lldMinGW
stdc++)
# ------------------------------------------------ #
# LLVM backend #

View File

@ -44,7 +44,7 @@ int lld_main(int Argc, const char **Argv, const char **outstr) {
*outstr = strdup(stderr.append(stdout).c_str());
return result.retCode;
return !result.retCode && result.canRunAgain;
}
} // extern "C"

View File

@ -1,35 +0,0 @@
cmake_minimum_required(VERSION 3.15...3.25)
project(gemstone_stdlib
VERSION 0.1.0
DESCRIPTION "gemstone programming language standard library"
LANGUAGES C)
set(CMAKE_C_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED TRUE)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
include_directories(${PROJECT_SOURCE_DIR}/src)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_SOURCE_DIR}/../bin/std")
# add native module libraries
file(GLOB_RECURSE STDLIB_IO_SOURCE_FILES src/io/*.c)
add_library(gscio ${STDLIB_IO_SOURCE_FILES})
file(GLOB_RECURSE STDLIB_MEM_SOURCE_FILES src/mem/*.c)
add_library(gscmem ${STDLIB_MEM_SOURCE_FILES})
file(GLOB_RECURSE STDLIB_OS_SOURCE_FILES src/os/*.c)
add_library(gscos ${STDLIB_OS_SOURCE_FILES})
file(GLOB_RECURSE STDLIB_MATH_SOURCE_FILES src/math/*.c)
add_library(gscmath ${STDLIB_MATH_SOURCE_FILES})
# Complete standard library
add_library(gscstd
${STDLIB_IO_SOURCE_FILES}
${STDLIB_MEM_SOURCE_FILES}
${STDLIB_OS_SOURCE_FILES}
${STDLIB_MATH_SOURCE_FILES})

View File

@ -1,16 +1,13 @@
[project]
name = "gemstone standard library"
name = "gscstd"
version = "0.1.0"
description = "Cross platform standard library for thr gemstone programming language."
description = "glibc build of the gemstone standard library"
license = "GPL-2.0"
authors = [ "Sven Vogel <sven.vogel123@web.de>" ]
[target.release]
root = "src/std.gem"
[target.gscstd]
import-paths = [ "glibc" ]
root = "glibc/std.gsc"
mode = "library"
output = "bin"
archive = "archive"
print_ast = false
print_asm = false
print_ir = false
opt = 3

21
lib/spec.md Normal file
View File

@ -0,0 +1,21 @@
# Gemstone Standard Library
## Modules
| Module name | Description |
|-------------|----------------------------------------------------------------------------------|
| `std` | Standard top level module importing all modules provided by the standard library |
| `types` | Commonly used types and aliases in submodules |
| `mem` | Memory management for allocations, frees and copy operations |
| `os` | Abstractions for common tasks related to the operating system |
| `io` | Basic wrapper for general purpose input/output operations |
| `fs` | File system operations extending functionality of the `io` module |
| `net` | Module for networking capabilities |
| `vec` | Vector data type implemented as growable array |
| `bootstrap` | Module required when compiling applications |
## Bootstrap
require dependency library in source
library name
mark function as external library source

View File

@ -1,7 +0,0 @@
import "def.gsc"
type unsigned int: bool
static bool: TRUE = 1
static bool: FALSE = 0

View File

@ -1,14 +0,0 @@
//
// Created by servostar on 6/3/24.
//
#ifndef GEMSTONE_STD_LIB_CAPI_H
#define GEMSTONE_STD_LIB_CAPI_H
#if defined(_WIN32) || defined (_WIN64)
#define PLATFORM_WINDOWS
#elif defined(unix) || defined(__unix) || defined(__unix__) || defined(__linux__)
#define PLATFORM_POSIX
#endif
#endif // GEMSTONE_STD_LIB_CAPI_H

View File

@ -1,38 +0,0 @@
# Author: Sven Vogel
# Edited: 25.05.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Standard Type definitions |
# `----------------------------------------`
# Unsigned integrals
type unsigned half half int: u8
type unsigned half int: u16
type unsigned int: u32
type unsigned double int: u64
type unsigned double double int: u128
# Signed integrals
type signed u8: i8
type signed u16: i16
type signed u32: i32
type signed u64: i64
type signed u128: i128
# IEEE-754 floating point
type signed half float: f16
type signed float: f32
type signed double float: f64
type signed double double float: f128
# String constant
type ref u8: cstr
# C style void pointer replacement
type ref u8: ptr

View File

@ -1,28 +0,0 @@
// Author: Sven Vogel
// Edited: 25.05.2024
// License: GPL-2.0
#ifndef GEMSTONE_STD_LIB_DEF_H_
#define GEMSTONE_STD_LIB_DEF_H_
#include <stdint.h>
#include <stddef.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
typedef float f32;
typedef double f64;
typedef u8* cstr;
typedef u8* ptr;
#endif // GEMSTONE_STD_LIB_DEF_H_

View File

@ -1,7 +0,0 @@
//
// Created by servostar on 6/10/24.
//
int main(int argc, char* argv[]) {
return 0;
}

View File

@ -0,0 +1,14 @@
# ----------------------------------------
# Bootstrap module for libgscstd-glibc
# used on GNU/Linux operating systems
import "os"
# main function is to be implemented by the application source
fun main()
# entrypoint function
fun start() {
main()
exit(0 as i32)
}

10
lib/src/glibc/os.gsc Normal file
View File

@ -0,0 +1,10 @@
include "types"
# from unistd.h
fun _exit(in i32: code)
# Return control back to the operating system
fun exit(in i32: code) {
_exit(code)
}

3
lib/src/glibc/std.gsc Normal file
View File

@ -0,0 +1,3 @@
include "os.gsc"
include "bootstrap.gsc"

19
lib/src/glibc/types.gsc Normal file
View File

@ -0,0 +1,19 @@
# Signed integer types
type signed half half int: i8
type signed half int: i16
type signed int: i32
type signed long int: i64
type signed long long int: i128
# Unsigned integer types
type unsigned half half int: u8
type unsigned half int: u16
type unsigned int: u32
type unsigned long int: u64
type unsigned long long int: u128
# Floating point
type half float: f16
type float: f32
type double float: f64

View File

@ -1,57 +0,0 @@
# Author: Sven Vogel
# Edited: 25.05.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Generic Input/Output |
# `----------------------------------------`
include "def.gsc"
# platform specific handle to an I/O device
# can be a file, buffer, window or something else
# NOTE: this reference is not meant to be dereferenced
# which can lead to errors and undefined behavior
type ptr: handle
# NULL handle representing an invalid handle on
# all platforms
handle: nullHandle = 0 as handle
# Returns a handle to this processes standard input I/O handle
# -- Implementation note
# On Linux this will return 0 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdin.3.html)
# On Windows the library will call `GetStdHandle(STD_INPUT_HANDLE)`
fun handle:getStdinHandle()
# Returns a handle to this processes standard input I/O handle
# -- Implementation note
# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stdout.3.html)
# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)`
fun handle:getStdoutHandle()
# Returns a handle to this processes standard input I/O handle
# -- Implementation note
# On Linux this will return 1 as is it convention under UNIX (see: https://www.man7.org/linux/man-pages/man3/stderr.3.html)
# On Windows the library will call `GetStdHandle(STD_OUTPUT_HANDLE)`
fun handle:getStderrHandle()
# Write `len` number of bytes from `buf` into the I/O resource specified
# by `dev`. Returns the number of bytes written.
# -- Implementation note
# On Linux this will use the syscall write
# On Windows this will use the WriteFile function
fun u32:writeBytes(in handle: dev, in ref u8: buf, in u32: len)
# Read atmost `len` bytes to `buf` from the I/O resource specified by `dev`
# Returns the number of read bytes in `written`
# -- Implementation note
# On Linux this will use the syscall read
# On Windows this will use the ReadFile function
fun u32:readBytes(in handle: dev, in ref u8: buf, in u32: len)
# Flushes the buffers of the I/O resource specified by `dev`
# -- Implementation note
# On Linux this will use the fsync function
# On Windows this will use the FlushFileBuffers function
fun flush(in handle: dev)

View File

@ -1,21 +0,0 @@
#ifndef GEMSTONE_STD_LIB_IO_H_
#define GEMSTONE_STD_LIB_IO_H_
#include <def/api.h>
typedef ptr handle;
handle getStdinHandle();
handle getStdoutHandle();
handle getStderrHandle();
u32 writeBytes(handle dev, u8* buf, u32 len);
u32 readBytes(handle dev, u8* buf, u32 len);
void flush(handle dev);
#endif //GEMSTONE_STD_LIB_IO_H_

View File

@ -1,79 +0,0 @@
#include <io/api.h>
#include <capi.h>
#if defined(PLATFORM_WINDOWS)
// Compile for Windows
#include <Windows.h>
// FIXME: error in case GetStdHandle return INVALID_HANDLE_VALUE
// FIXME: error in case functions return 0
handle getStdinHandle(handle* stdin) {
return GetStdHandle(STD_INPUT_HANDLE);
}
handle getStdoutHandle(handle* stdout) {
return GetStdHandle(STD_OUTPUT_HANDLE);
}
handle getStderrHandle(handle* stderr) {
return GetStdHandle(STD_ERROR_HANDLE);
}
u32 writeBytes(handle dev, u8* buf, u32 len) {
u32 bytesWritten = 0;
WriteFile((HANDLE) dev, buf, len, &bytesWritten, NULL);
return bytesWritten;
}
u32 readBytes(handle dev, u8* buf, u32 len) {
u32 bytesRead = 0;
ReadFile((HANDLE) dev, buf, len, &bytesRead, NULL);
return bytesRead;
}
void flush(handle dev) {
FlushFileBuffers((HANDLE) dev);
}
#elif defined(PLATFORM_POSIX)
// Compile for Linux and BSD
#include <unistd.h>
#include <stdio.h>
// savely cast a 64-bit pointer down to a 32-bit value
// this assumes that 64-bit system will use 32-bit handles
// which are stored as 64-bit by zero extending
#define TO_INT(x) ((int)(long int)(x))
handle getStdinHandle() {
return (handle) STDIN_FILENO;
}
handle getStdoutHandle() {
return (handle) STDOUT_FILENO;
}
handle getStderrHandle() {
return (handle) STDERR_FILENO;
}
u32 writeBytes(handle dev, u8* buf, u32 len) {
return write(TO_INT(dev), buf, len);
}
u32 readBytes(handle dev, u8* buf, u32 len) {
return read(TO_INT(dev), buf, len);
}
void flush(handle dev) {
fsync(TO_INT(dev));
}
#endif

View File

@ -1,12 +0,0 @@
# Author: Sven Vogel
# Edited: 01.08.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Mathematical utilities |
# `----------------------------------------`
include "def.gsc"
# Compute the module of a by base b and store the result in c
fun mod(in u32: a, in u32: b)(out u32: c)

View File

@ -1,9 +0,0 @@
#ifndef GEMSTONE_STD_LIB_MATH_H_
#define GEMSTONE_STD_LIB_MATH_H_
#include <def/api.h>
void mod(u32 a, u32 b, u32* c);
#endif //GEMSTONE_STD_LIB_MATH_H_

View File

@ -1,10 +0,0 @@
//
// Created by servostar on 01.08.24.
//
#include <math/api.h>
#include <capi.h>
void mod(u32 a, u32 b, u32* c) {
c[0] = a % b;
}

View File

@ -1,27 +0,0 @@
# Author: Sven Vogel
# Edited: 25.05.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Memory Management |
# `----------------------------------------`
include "def.gsc"
# Allocate `len` bytes of heap memory
# Returns a pointer to the memory as `ptr`
fun heapAlloc(in u32: len)(out ref u8: ptr)
# Rellocate `len` bytes of heap memory
# Returns a pointer to the memory as `ptr`
fun heapRealloc(in u32: len, in out ref u8: ptr)
# Free a block of memory
fun heapFree(in ref u8: ptr)
# Copy `len` bytes from `dst` into `src`
fun copy(in ref u8: dst, in ref u8: src, in u32: len)
# Fill `len` bytes of `dst` with `byte`
fun fill(in ref u8: dst, in u8: byte, in u32: len)

View File

@ -1,17 +0,0 @@
#ifndef GEMSTONE_STD_LIB_MEM_H_
#define GEMSTONE_STD_LIB_MEM_H_
#include <def/api.h>
void heapAlloc(u32 len, u8** ptr);
void heapRealloc(u32 len, u8** ptr);
void heapFree(u8* ptr);
void copy(u8* dst, u8* src, u32 len);
void fill(u8* dst, u8 byte, u32 len);
#endif // GEMSTONE_STD_LIB_MEM_H_

View File

@ -1,52 +0,0 @@
#include <mem/api.h>
#include <capi.h>
#if defined(PLATFORM_WINDOWS)
#include <Windows.h>
#define HEAP_API_GLOBAL_FLAGS HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS
void heapAlloc(u32 len, u8** ptr) {
HANDLE heap = GetProcessHeap();
*ptr = HeapAlloc(heap, HEAP_API_GLOBAL_FLAGS, len);
}
void heapRealloc(u32 len, u8** ptr) {
HANDLE heap = GetProcessHeap();
*ptr = HeapReAlloc(heap, HEAP_API_GLOBAL_FLAGS, *ptr, len);
}
void heapFree(u8* ptr) {
HANDLE heap = GetProcessHeap();
HeapFree(heap, ptr);
}
#elif defined(PLATFORM_POSIX)
#include <malloc.h>
void heapAlloc(u32 len, u8** ptr) {
*ptr = malloc(len);
}
void heapRealloc(u32 len, u8** ptr) {
*ptr = realloc(*ptr, len);
}
void heapFree(u8* ptr) {
free(ptr);
}
#endif
#include <string.h>
void copy(u8* dst, u8* src, u32 len) {
memcpy(dst, src, len);
}
void fill(u8* dst, u8 byte, u32 len) {
memset(dst, byte, len);
}

View File

@ -1,25 +0,0 @@
# Author: Sven Vogel
# Edited: 03.06.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Operating System |
# `----------------------------------------`
include "def.gsc"
# Return a hard coded C string identifying the underlying operating system
# Will return one of the following:
# - "windows" (for Windows 7, Windows 10 and Windows 11)
# - "unix" (for GNU/Linux and BSD)
fun getPlatformName(out cstr: name)
# Return a C string to the value of an environment varible named
# after the C string name.
fun getEnvVar(in cstr: name)(out cstr: value)
# Set the value of an environment variable with name to value.
fun setEnvVar(in cstr: name, in cstr: value)
# Unset a specific environment variable
fun unsetEnvVar(in cstr: name)

View File

@ -1,18 +0,0 @@
//
// Created by servostar on 6/3/24.
//
#ifndef GEMSTONE_STD_LIB_OS_H
#define GEMSTONE_STD_LIB_OS_H
#include <def/api.h>
void getPlatformName(cstr* name);
void getEnvVar(cstr name, cstr* value);
void setEnvVar(cstr name, cstr value);
void unsetEnvVar(cstr name);
#endif // GEMSTONE_STD_LIB_OS_H

View File

@ -1,36 +0,0 @@
//
// Created by servostar on 6/3/24.
//
#include <capi.h>
#include <os/api.h>
#if defined(PLATFORM_WINDOWS)
void getPlatformName(cstr* name) {
*name = (u8*) "windows";
}
#elif defined(PLATFORM_POSIX)
void getPlatformName(cstr * name) {
*name = (u8*) "posix";
}
#endif
// Implementation based on libc
#include <stdlib.h>
void getEnvVar(cstr name, cstr* value) {
*value = (cstr) getenv((char*) name);
}
void setEnvVar(cstr name, cstr value) {
setenv((char*) name, (char*) value, true);
}
void unsetEnvVar(cstr name) {
unsetenv((char*) name);
}

View File

@ -1,19 +0,0 @@
# Author: Sven Vogel
# Edited: 25.05.2024
# License: GPL-2.0
# ,----------------------------------------.
# | Gemstone Standard Library |
# `----------------------------------------`
# standard type definitions
include "def.gsc"
# I/O operations
include "io.gsc"
# memory management
include "mem.gsc"
# mathematical utilities
include "math.gsc"

View File

@ -7,7 +7,7 @@
#include <cfg/opt.h>
#define DEFAULT_DRIVER "clang"
#define DEFAULT_DRIVER "ld.lld"
//! @brief Function a binary driver used to link files
typedef bool (*driver_link)(TargetLinkConfig*);

View File

@ -2,6 +2,8 @@
// Created by servostar on 18.07.24.
//
#include "lldc/lldc.h"
#include <io/files.h>
#include <link/clang/driver.h>
#include <link/gcc/driver.h>
@ -9,7 +11,7 @@
#include <mem/cache.h>
#include <sys/log.h>
static driver_init AVAILABLE_DRIVER[] = {clang_get_driver, gcc_get_driver};
static driver_init AVAILABLE_DRIVER[] = {clang_get_driver, gcc_get_driver, lldc_get_driver};
static GHashTable* binary_driver = NULL;

54
src/link/lldc/lldc.c Normal file
View File

@ -0,0 +1,54 @@
//
// Created by servostar on 8/11/24.
//
#include "lldc.h"
#include <io/files.h>
#include <mem/cache.h>
#include <stdio.h>
extern int lld_main(int Argc, const char **Argv, const char **outstr);
bool lldc_link(TargetLinkConfig* config) {
GArray* arguments = mem_new_g_array(MemoryNamespaceLld, sizeof(char*));
char* linker = "ld.lld";
g_array_append_val(arguments, linker);
for (guint i = 0; i < config->object_file_names->len; i++) {
char* obj = g_array_index(config->object_file_names, char*, i);
g_array_append_val(arguments, obj);
}
char* output_flag = "-o";
g_array_append_val(arguments, output_flag);
g_array_append_val(arguments, config->output_file);
for (guint i = 0; i < arguments->len; i++) {
printf("%s ", g_array_index(arguments, char*, i));
}
printf("\n");
const char* message = NULL;
const bool code = lld_main(arguments->len, (const char**) arguments->data, &message);
free((void*) message);
if (!code) {
print_message(Error, message);
}
return code;
}
BinaryDriver* lldc_get_driver() {
BinaryDriver* driver = mem_alloc(MemoryNamespaceLld, sizeof(BinaryDriver));
driver->name = "ld.lld";
driver->link_func = &lldc_link;
return driver;
}

14
src/link/lldc/lldc.h Normal file
View File

@ -0,0 +1,14 @@
//
// Created by servostar on 8/11/24.
//
#ifndef LLDC_H
#define LLDC_H
#include <link/driver.h>
bool lldc_link(TargetLinkConfig* config);
BinaryDriver* lldc_get_driver();
#endif //LLDC_H

View File

@ -92,7 +92,7 @@ TargetLinkConfig* lld_create_link_config(__attribute__((unused))
for (guint i = 0; i < module->imports->len; i++) {
const char* dependency = g_array_index(module->imports, const char*, i);
const char* library = g_strjoin("", "libgsc", dependency, ".a", NULL);
const char* library = g_strjoin("", "libgsc", dependency, ".o", NULL);
const char* dependency_object =
get_absolute_link_path(target_config, library);

16
tests/box/build.toml Normal file
View File

@ -0,0 +1,16 @@
[project]
name = "Stdlib tests"
version = "0.1.0"
description = "Test applications for the GSC standard library."
license = "GPL-2.0"
authors = [ "Sven Vogel <sven.vogel123@web.de>" ]
[target.prime]
import-paths = [ "." ]
root = "main.gsc"
mode = "application"
output = "bin"
archive = "archive"
[dependencies]
gscstd = { path = "../../lib" }

6
tests/box/main.gsc Normal file
View File

@ -0,0 +1,6 @@
import "std"
fun main() {
i32: u = 0 as i32
}