Build system improvements. Target changes x64-windows -> windows-x64, x64-darwin -> macos-x64. Improved mac support. LLD linking for Mac, Windows, Linux. Cross linking for Mac, Windows. Clean up string use.

This commit is contained in:
Christoffer Lerno
2022-04-18 18:31:49 +02:00
parent 7df7dd2933
commit 0cf110f763
210 changed files with 2292 additions and 1271 deletions

View File

@@ -38,7 +38,7 @@ jobs:
- name: Build testproject
run: |
cd resources/testproject
../../build/c3c build --debug-log
../../build/c3c run --debug-log
- name: run compiler tests
run: |
@@ -73,7 +73,7 @@ jobs:
- name: Build testproject
run: |
cd resources/testproject
../../build/c3c build --debug-log
../../build/c3c run --debug-log
- name: run compiler tests
run: |
@@ -118,7 +118,12 @@ jobs:
- name: Build testproject
run: |
cd resources/testproject
../../build/c3c build --debug-log
../../build/c3c run --debug-log
- name: Build testproject direct linker
run: |
cd resources/testproject
../../build/c3c run --debug-log --forcelinker
- name: run compiler tests
run: |
@@ -150,7 +155,12 @@ jobs:
- name: Build testproject
run: |
cd resources/testproject
../../build/c3c build --debug-log
../../build/c3c run --debug-log
- name: Build testproject direct linker
run: |
cd resources/testproject
../../build/c3c run --debug-log --forcelinker
- name: run compiler tests
run: |

View File

@@ -84,12 +84,18 @@ llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})
file(COPY ${CMAKE_SOURCE_DIR}/lib DESTINATION ${CMAKE_BINARY_DIR})
# These don't seem to be reliable on windows.
if(UNIX)
message(STATUS "using find_library")
# find_library(TB_LIB NAMES tinybackend.a PATHS ${CMAKE_SOURCE_DIR}/resources/tblib)
find_library(LLD_COFF NAMES lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS})
find_library(LLD_COMMON NAMES lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
find_library(LLD_ELF NAMES lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS})
if (${LLVM_PACKAGE_VERSION} VERSION_LESS 14)
find_library(LLD_MACHO NAMES lldMachO2.a liblldMachO2.a PATHS ${LLVM_LIBRARY_DIRS})
else()
find_library(LLD_MACHO NAMES lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
endif()
find_library(LLD_MACHO NAMES lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
find_library(LLD_MINGW NAMES lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
find_library(LLD_WASM NAMES lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
@@ -113,9 +119,18 @@ if(UNIX)
${LLD_YAML}
${LLD_CORE}
)
message(STATUS "linking to llvm libs ${llvm_libs} ${lld_libs}")
endif()
if(APPLE)
set(lld_libs ${lld_libs} xar)
endif()
message(STATUS "linking to llvm libs ${llvm_libs} ${lld_libs}")
else()
if(${LLVM_PACKAGE_VERSION} VERSION_LESS 14)
set(lld_libs lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO2 lldYAML)
else()
set(lld_libs lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML)
endif()
endif()
message(STATUS "Found LLD ${lld_libs}")
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
@@ -138,6 +153,7 @@ add_executable(c3c
src/compiler/float.c
src/compiler/headers.c
src/compiler/lexer.c
src/compiler/libraries.c
src/compiler/linker.c
src/compiler/llvm_codegen.c
src/compiler/llvm_codegen_c_abi_aarch64.c
@@ -196,11 +212,12 @@ add_executable(c3c
src/utils/vmem.h
src/utils/whereami.c
src/compiler/decltable.c
src/compiler/mac_support.c
src/compiler/tilde_codegen_storeload.c
src/compiler/llvm_codegen_storeload.c
src/compiler/tilde_codegen_expr.c
src/compiler/tilde_codegen_stmt.c
src/compiler/tilde_codegen_type.c)
src/compiler/tilde_codegen_type.c src/compiler/windows_support.c)
if(NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC")
message(STATUS "using gcc/clang warning switches")
@@ -231,8 +248,8 @@ else()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -LIBPATH:C:\\llvm\\llvm\\build\\Release\\lib") # needed for lldCommon.lib
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -LIBPATH:${LLVM_LIBPATH}") # This doesn't seem to work for some reason
message(STATUS "${LLVM_LIBPATH}")
target_link_libraries(c3c debug ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML Advapi32)
target_link_libraries(c3c optimized ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML Advapi32)
target_link_libraries(c3c debug ${llvm_libs} c3c_wrappers ${lld_libs} Advapi32)
target_link_libraries(c3c optimized ${llvm_libs} c3c_wrappers ${lld_libs} Advapi32)
endif()
if (WIN32)

View File

@@ -0,0 +1,167 @@
module foo;
extern fn void printf(char*, ...);
enum Foo : int (int offset, char* extra_name, double x)
{
BAZ(12, "hello", 3.0),
BOO(33, "oekfe", 4.0) = 3,
}
fn void main()
{
int screenWidth = 800;
int screenHeight = 450;
raylib::init_window(screenWidth, screenHeight, "raylib [core] example - keyboard input");
Vector2 ballPosition = { (float)screenWidth/2, (float)screenHeight/2 };
raylib::set_target_fps(60); // Set our game to run at 60 frames-per-second
//--------------------------------------------------------------------------------------
foo2::tester(screenHeight);
// Main game loop
while (!raylib::window_should_close()) // Detect window close button or ESC key
{
// Update
//----------------------------------------------------------------------------------
if (raylib::is_key_down(KeyboardKey.RIGHT)) ballPosition.x += 2.0f;
if (raylib::is_key_down(KeyboardKey.LEFT)) ballPosition.x -= 2.0f;
if (raylib::is_key_down(KeyboardKey.UP)) ballPosition.y -= 2.0f;
if (raylib::is_key_down(KeyboardKey.DOWN)) ballPosition.y += 2.0f;
//----------------------------------------------------------------------------------
// Draw
//----------------------------------------------------------------------------------
raylib::begin_drawing();
raylib::clear_background(raylib::RAYWHITE);
raylib::draw_text("move the ball with arrow keys", 10, 10, 20, raylib::DARKGRAY);
raylib::draw_circle_v(ballPosition, 50, raylib::MAROON);
raylib::end_drawing();
//----------------------------------------------------------------------------------
}
// De-Initialization
//--------------------------------------------------------------------------------------
raylib::close_window(); // Close window and OpenGL context
//--------------------------------------------------------------------------------------
}
/*
struct Game
{
int answer;
bool done;
int guesses;
int high;
}
int err_count = 0;
import "core:bufio"
import "core:fmt"
import "core:io"
import "core:mem"
import "core:os"
import "core:strconv"
import "core:time"
import "core:math/rand"
Game :: struct {
answer: int,
done: bool,
guesses: int,
high: int,
}
int err_count = 0;
*/
/*
fn int ask_guess(int high)
{
libc::printf("Guess a number between 1 and %d: ", high);
}
ask_guess :: proc(high: int) -> (result: int, ok: bool) {
fmt.printf("Guess a number between 1 and %d: ", high)
if text, ok := read_line(); ok {
defer mem.delete(text)
return strconv.parse_int(s = text, base = 10)
}
return
}
ask_guess_multi :: proc(high: int) -> int {
for {
if result, ok := ask_guess(high); ok {
return result
}
fmt.println("I didn't understand")
err_count += 1
}
}
pick_answer :: proc(high: int, r: ^rand.Rand) -> int {
return rand.int_max(high, r) + 1
}
play :: proc(game: ^Game) {
for !game.done {
guess := ask_guess_multi(game.high)
report(game^, guess)
game^ = update(game^, guess)
}
}
read_line :: proc() -> (result: string, ok: bool) {
// See also:
// - https://github.com/odin-lang/Odin/issues/1214
// - https://p.teknik.io/Raw/IT996
s := os.stream_from_handle(os.stdin)
r: bufio.Reader
bufio.reader_init(&r, io.Reader{s})
defer bufio.reader_destroy(&r)
if line, err := bufio.reader_read_string(&r, '\n'); err == .None {
return line[:len(line) - 1], true
}
return
}
report :: proc(game: Game, guess: int) {
// game.done = true
// fmt.println(&game)
description := (
"too low" if guess < game.answer else
"too high" if guess > game.answer else
"the answer!"
)
fmt.println(guess, "is", description)
}
update :: proc(game: Game, guess: int) -> (next: Game) {
next = game
next.done = guess == game.answer
next.guesses += 1
return
}
main :: proc() {
high :: 100
r := rand.create(transmute(u64)time.now())
// Or use nil for default random.
answer := pick_answer(high, &r)
game := Game {answer = answer, done = false, guesses = 0, high = high}
play(&game)
fmt.println("Finished in", game.guesses, "guesses");
fmt.println("Total input errors:", err_count)
}
*/
module foo2;
fn void tester(int x)
{
assert(x > 1000, "Shit!");
}

View File

@@ -9,5 +9,5 @@ fn int main()
printf("Hello World!\n");
bar::test();
printf("Hello double: %d\n", test_doubler(11));
return 1;
return 17;
}

View File

@@ -14,6 +14,7 @@
#include <utils/lib.h>
#include "../utils/whereami.h"
extern int llvm_version_major;
static int arg_index;
static int arg_count;
@@ -23,30 +24,30 @@ extern const char* llvm_version;
extern const char* llvm_target;
char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
[X86_FREEBSD] = "x86-freebsd",
[X86_OPENBSD] = "x86-openbsd",
[X86_NETBSD] = "x86-netbsd",
[X86_MCU] = "x86-mcu",
[X86_ELF] = "x86-elf",
[X86_WINDOWS] = "x86-windows",
[X86_LINUX] = "x86-linux",
[X64_DARWIN] = "x64-darwin",
[X64_LINUX] = "x64-linux",
[X64_WINDOWS] = "x64-windows",
[X64_WINDOWS_GNU] = "x64-mingw",
[X64_FREEBSD] = "x64-freebsd",
[X64_OPENBSD] = "x64-openbsd",
[X64_NETBSD] = "x64-netbsd",
[X64_ELF] = "x64-elf",
[AARCH64_LINUX] = "aarch64-linux",
[AARCH64_DARWIN] = "aarch64-darwin",
[AARCH64_ELF] = "aarch64-elf",
[RISCV32_LINUX] = "riscv32-linux",
[RISCV32_ELF] = "riscv32-elf",
[RISCV64_LINUX] = "riscv64-linux",
[RISCV64_ELF] = "riscv64-elf",
[WINDOWS_X86] = "windows-x86",
[WINDOWS_X64] = "windows-x64",
[MINGW_X64] = "mingw-x64",
[MACOS_X64] = "macos-x64",
[MACOS_AARCH64] = "macos-aarch64",
[LINUX_X86] = "linux-x86",
[LINUX_X64] = "linux-x64",
[LINUX_AARCH64] = "linux-aarch64",
[LINUX_RISCV32] = "linux-riscv32",
[LINUX_RISCV64] = "linux-riscv64",
[WASM32] = "wasm32",
[WASM64] = "wasm64",
[ELF_X86] = "elf-x86",
[ELF_X64] = "elf-x64",
[ELF_AARCH64] = "elf-aarch64",
[ELF_RISCV32] = "elf-riscv32",
[ELF_RISCV64] = "elf-riscv64",
[FREEBSD_X86] = "freebsd-x86",
[FREEBSD_X64] = "freebsd-x64",
[OPENBSD_X86] = "openbsd-x86",
[OPENBSD_X64] = "openbsd-x64",
[NETBSD_X86] = "netbsd-x86",
[NETBSD_X64] = "netbsd-x64",
[MCU_X86] = "mcu-x86",
};
#define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__)
@@ -74,7 +75,8 @@ static void usage(void)
OUTPUT("Options:");
OUTPUT(" --tinybackend - Use the TinyBackend for compilation.");
OUTPUT(" --stdlib <dir> - Use this directory as the C3 standard library path.");
OUTPUT(" --lib <dir> - Use this directory as the C3 library path.");
OUTPUT(" --libdir <dir> - Add this directory to the C3 library search paths.");
OUTPUT(" --lib <name> - Add this library to the compilation.");
OUTPUT(" --path <dir> - Use this as the base directory for the current command.");
OUTPUT(" --template <template> - Use a different template: \"lib\", \"static-lib\" or a path.");
OUTPUT(" --about - Prints a short description of C3.");
@@ -103,6 +105,7 @@ static void usage(void)
OUTPUT(" -l <library> - Link with the library provided.");
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
OUTPUT(" -z <argument> - Send the <argument> as a parameter to the linker.");
OUTPUT(" --forcelinker - Force linker usage over using when doing non-cross linking.");
OUTPUT("");
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE");
OUTPUT(" --x86vec=<option> - Set max level of vector instructions: none, mmx, sse, avx, avx512.");
@@ -114,6 +117,12 @@ static void usage(void)
OUTPUT(" --list-attributes - List all attributes.");
OUTPUT(" --list-builtins - List all builtins.");
OUTPUT(" --list-precedence - List operator precedence order.");
OUTPUT("");
OUTPUT(" --winsdk <dir> - Set the directory for Windows system library files for cross compilation.");
OUTPUT(" --wincrt=<option> - Windows CRT linking: none, static, dynamic (default).");
OUTPUT("");
OUTPUT(" --macossdk <dir> - Set the directory for the MacOS SDK for cross compilation.");
#ifndef NDEBUG
OUTPUT(" --debug-log - Print debug logging to stdout.");
#endif
@@ -315,7 +324,7 @@ static void add_linker_arg(BuildOptions *options, const char *arg)
static int parse_multi_option(const char *start, unsigned count, const char** elements)
{
const char *arg = current_arg;
int select = str_in_list(start, count, elements);
int select = str_findlist(start, count, elements);
if (select < 0) error_exit("error: %.*s invalid option '%s' given.", (int)(start - arg), start, arg);
return select;
}
@@ -416,7 +425,7 @@ static void parse_option(BuildOptions *options)
{
if (at_end() || next_is_opt()) error_exit("error: -l needs a library name.");
const char *lib = next_arg();
const char *framework = str_without_suffix(lib, ".framework");
const char *framework = str_remove_suffix(lib, ".framework");
if (framework)
{
add_linker_arg(options, "-framework");
@@ -462,6 +471,18 @@ static void parse_option(BuildOptions *options)
options->symtab_size = next_highest_power_of_2(symtab);
return;
}
if (match_longopt("forcelinker"))
{
if (llvm_version_major > 12)
{
options->force_linker = true;
}
else
{
printf("Force linking ignored on LLVM 12 and earlier.\n");
}
return;
}
if (match_longopt("version"))
{
print_version();
@@ -580,11 +601,41 @@ static void parse_option(BuildOptions *options)
options->panicfn = next_arg();
return;
}
if (match_longopt("macossdk"))
{
if (at_end() || next_is_opt()) error_exit("error: --macossdk needs a directory.");
options->macos.sdk = check_dir(next_arg());
return;
}
if (match_longopt("winsdk"))
{
if (at_end() || next_is_opt()) error_exit("error: --winsdk needs a directory.");
options->win.sdk = check_dir(next_arg());
return;
}
if ((argopt = match_argopt("wincrt")))
{
options->win.crt_linking = (WinCrtLinking)parse_multi_option(argopt, 3, wincrt_linking);
return;
}
if (match_longopt("lib"))
{
if (at_end() || next_is_opt()) error_exit("error: --lib needs a directory.");
if (options->lib_count == MAX_LIB_DIRS) error_exit("Max %d libraries may be specified.", MAX_LIB_DIRS);
options->lib_dir[options->lib_count++] = check_dir(next_arg());
if (at_end() || next_is_opt()) error_exit("error: --lib needs a name.");
const char *name = next_arg();
if (!str_is_valid_lowercase_name(name))
{
char *name_copy = strdup(name);
str_ellide_in_place(name_copy, 32);
error_exit("Invalid library name '%s', it should be something like 'foo_lib'.", name_copy);
}
options->libs[options->lib_count++] = name;
return;
}
if (match_longopt("libdir"))
{
if (at_end() || next_is_opt()) error_exit("error: --libdir needs a directory.");
if (options->lib_dir_count == MAX_LIB_DIRS) error_exit("Max %d library directories may be specified.", MAX_LIB_DIRS);
options->lib_dir[options->lib_dir_count++] = check_dir(next_arg());
return;
}
if (match_longopt("test"))
@@ -645,6 +696,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
.reloc_model = RELOC_DEFAULT,
.backend = BACKEND_LLVM,
.x86_vector_capability = X86VECTOR_DEFAULT,
.win.crt_linking = WIN_CRT_DEFAULT,
.files = NULL
};
for (int i = DIAG_NONE; i < DIAG_WARNING_TYPE; i++)

View File

@@ -144,6 +144,20 @@ static const char *vector_capability[5] = {
[X86VECTOR_AVX512] = "avx512",
};
typedef enum
{
WIN_CRT_DEFAULT = -1,
WIN_CRT_NONE = 0,
WIN_CRT_DYNAMIC = 1,
WIN_CRT_STATIC = 2,
} WinCrtLinking;
static const char *wincrt_linking[3] = {
[WIN_CRT_NONE] = "none",
[WIN_CRT_DYNAMIC] = "dynamic",
[WIN_CRT_STATIC] = "static",
};
typedef enum
{
RELOC_DEFAULT = -1,
@@ -173,44 +187,53 @@ typedef enum
typedef enum
{
ARCH_OS_TARGET_DEFAULT = 0,
X86_FREEBSD,
X86_OPENBSD,
X86_NETBSD,
X86_LINUX,
X86_WINDOWS,
X86_MCU,
X86_ELF,
X64_DARWIN,
X64_LINUX,
X64_NETBSD,
X64_FREEBSD,
X64_OPENBSD,
X64_WINDOWS,
X64_WINDOWS_GNU,
X64_ELF,
AARCH64_LINUX,
AARCH64_DARWIN,
AARCH64_ELF,
RISCV32_LINUX,
RISCV32_ELF,
RISCV64_LINUX,
RISCV64_ELF,
LINUX_X86,
LINUX_X64,
WINDOWS_X86,
WINDOWS_X64,
MINGW_X64,
MACOS_X64,
MACOS_AARCH64,
LINUX_AARCH64,
LINUX_RISCV32,
LINUX_RISCV64,
WASM32,
WASM64,
ARCH_OS_TARGET_LAST = WASM64
ELF_X86,
ELF_X64,
ELF_AARCH64,
ELF_RISCV32,
ELF_RISCV64,
FREEBSD_X86,
FREEBSD_X64,
OPENBSD_X86,
OPENBSD_X64,
NETBSD_X86,
NETBSD_X64,
MCU_X86,
ARCH_OS_TARGET_LAST = MCU_X86
} ArchOsTarget;
typedef struct BuildOptions_
{
const char* lib_dir[MAX_LIB_DIRS];
const char* linker_args[MAX_LIB_DIRS];
const char* linker_lib_dir[MAX_LIB_DIRS];
const char* linker_libs[MAX_LIB_DIRS];
const char* std_lib_dir;
const char *lib_dir[MAX_LIB_DIRS];
int lib_dir_count;
const char *libs[MAX_LIB_DIRS];
int lib_count;
const char* linker_args[MAX_LIB_DIRS];
int linker_arg_count;
const char* linker_lib_dir[MAX_LIB_DIRS];
int linker_lib_dir_count;
const char* linker_libs[MAX_LIB_DIRS];
int linker_lib_count;
const char* std_lib_dir;
struct {
const char *sdk;
WinCrtLinking crt_linking;
} win;
struct {
const char *sdk;
} macos;
int build_threads;
const char** files;
const char* output_name;
@@ -231,6 +254,7 @@ typedef struct BuildOptions_
bool emit_bitcode;
bool test_mode;
bool no_stdlib;
bool force_linker;
const char *panicfn;
RelocModel reloc_model;
X86VectorCapability x86_vector_capability;
@@ -253,15 +277,35 @@ typedef enum
TARGET_TYPE_TEST
} TargetType;
typedef struct
{
ArchOsTarget arch_os;
const char **link_flags;
const char **linked_libs;
const char **depends;
} LibraryTarget;
typedef struct
{
const char *dir;
const char *provides;
const char **depends;
LibraryTarget *target_used;
LibraryTarget **targets;
} Library;
typedef struct
{
TargetType type;
Library **library_list;
const char *name;
const char *version;
const char *langrev;
const char **source_dirs;
const char **sources;
const char **libraries;
const char **libdirs;
const char **libs;
const char **linker_libdirs;
const char *cpu;
const char **link_args;
bool run_after_compile : 1;
@@ -275,6 +319,7 @@ typedef struct
bool no_stdlib : 1;
bool emit_object_files : 1;
bool no_link : 1;
bool force_linker : 1;
OptimizationLevel optimization_level;
SizeOptimizationLevel size_optimization_level;
DebugInfo debug_info;
@@ -296,6 +341,15 @@ typedef struct
bool trap_on_wrap : 1;
bool safe_mode : 1;
} feature;
struct
{
const char *sdk;
} macos;
struct
{
const char *sdk;
WinCrtLinking crt_linking;
} win;
} BuildTarget;

View File

@@ -14,58 +14,54 @@ void load_library_files(void) {}
void load_files(void) {}
#if defined(_M_X64) || defined(_M_AMD64)
#if defined(__MINGW32__)
ArchOsTarget default_target = X64_WINDOWS_GNU;
#else
ArchOsTarget default_target = X64_WINDOWS;
#endif
ArchOsTarget default_target = WINDOWS_X64;
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
#if defined(__MACH__)
ArchOsTarget default_target = X64_DARWIN;
ArchOsTarget default_target = MACOS_X64;
#elif defined(__linux__) && __linux__
ArchOsTarget default_target = X64_LINUX;
ArchOsTarget default_target = LINUX_X64;
#elif defined(__NetBSD__)
ArchOsTarget default_target = X64_NETBSD;
ArchOsTarget default_target = NETBSD_X64;
#elif defined(__FreeBSD__)
ArchOsTarget default_target = X64_FREEBSD;
ArchOsTarget default_target = FREEBSD_X64;
#elif defined(__OpenBSD__)
ArchOsTarget default_target = X64_OPENBSD;
ArchOsTarget default_target = OPENBSD_X64;
#else
ArchOsTarget default_target = X64_ELF;
ArchOsTarget default_target = ELF_X64;
#endif
#elif defined(__aarch64__) || defined(_M_ARM64)
#if defined(__MACH__)
ArchOsTarget default_target = AARCH64_DARWIN;
ArchOsTarget default_target = MACOS_AARCH64;
#elif defined(__linux__) && __linux__
ArchOsTarget default_target = AARCH64_LINUX;
ArchOsTarget default_target = LINUX_AARCH64;
#else
ArchOsTarget default_target = AARCH64_ELF;
ArchOsTarget default_target = ELF_AARCH64;
#endif
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
#if defined(__linux__) && __linux__
ArchOsTarget default_target = X86_LINUX;
ArchOsTarget default_target = LINUX_X86;
#elif defined(__FreeBSD__)
ArchOsTarget default_target = X86_FREEBSD;
ArchOsTarget default_target = FREEBSD_X86;
#elif defined(__OpenBSD__)
ArchOsTarget default_target = X86_OPENBSD;
ArchOsTarget default_target = OPENBSD_X86;
#elif defined(__NetBSD__)
ArchOsTarget default_target = X86_NETBSD;
ArchOsTarget default_target = NETBSD_X86;
#elif defined(_MSC_VER) && _MSC_VER
ArchOsTarget default_target = X86_WINDOWS;
ArchOsTarget default_target = WINDOWS_X86;
#else
ArchOsTarget default_target = X86_ELF;
ArchOsTarget default_target = ELF_X86;
#endif
#elif defined(__riscv32)
#if defined(__linux__) && __linux__
ArchOsTarget default_target = RISCV32_LINUX;
ArchOsTarget default_target = LINUX_RISCV32;
#else
ArchOsTarget default_target = RISCV32_ELF;
ArchOsTarget default_target = ELF_RISCV32;
#endif
#elif defined(__riscv64)
#if defined(__linux__) && __linux__
ArchOsTarget default_target = RISCV64_LINUX;
ArchOsTarget default_target = LINUX_RISCV64;
#else
ArchOsTarget default_target = RISCV64_ELF;
ArchOsTarget default_target = ELF_RISCV64;
#endif
#else
ArchOsTarget default_target = ARCH_OS_TARGET_DEFAULT;
@@ -163,7 +159,11 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
}
target->no_stdlib = options->no_stdlib;
target->emit_llvm = options->emit_llvm;
target->force_linker = options->force_linker;
target->panicfn = options->panicfn;
if (options->macos.sdk) target->macos.sdk = options->macos.sdk;
if (options->win.sdk) target->win.sdk = options->win.sdk;
if (options->win.crt_linking != WIN_CRT_DEFAULT) target->win.crt_linking = options->win.crt_linking;
if (options->x86_vector_capability != X86VECTOR_DEFAULT)
{
target->feature.x86_vector_capability = options->x86_vector_capability;
@@ -198,6 +198,14 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
target->emit_llvm = false;
target->emit_object_files = false;
}
for (int i = 0; i < options->lib_dir_count; i++)
{
vec_add(target->libdirs, options->lib_dir[i]);
}
for (int i = 0; i < options->lib_count; i++)
{
vec_add(target->libs, options->libs[i]);
}
}
void init_default_build_target(BuildTarget *target, BuildOptions *options)
@@ -214,6 +222,7 @@ void init_default_build_target(BuildTarget *target, BuildOptions *options)
.arch_os_target = ARCH_OS_TARGET_DEFAULT,
.reloc_model = RELOC_DEFAULT,
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
.win.crt_linking = WIN_CRT_DEFAULT,
};
update_build_target_from_options(target, options);
}

View File

@@ -47,7 +47,7 @@ static int get_valid_string_setting(JSONObject *json, const char *key, const cha
}
if (value->type == J_STRING)
{
int res = str_in_list(value->str, count, values);
int res = str_findlist(value->str, count, values);
if (res >= 0) return res + first_result;
}
error_exit("%s had an invalid value for '%s', expected %s", category, key, expected);
@@ -109,6 +109,17 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
const char *langrev = get_valid_string(json, "langrev", type, false);
const char **source_dirs = get_valid_array(json, "sources", type, target->source_dirs == NULL);
const char **libraries = get_valid_array(json, "libs", type, false);
VECEACH(libraries, i)
{
if (!str_is_valid_lowercase_name(libraries[i]))
{
char *name = strdup(libraries[i]);
str_ellide_in_place(name, 32);
error_exit("Error reading %s: invalid library target '%s'.", PROJECT_JSON, name);
}
}
const char **libdirs = get_valid_array(json, "libdir", type, false);
static const char *debug_infos[3] = {
[DEBUG_INFO_FULL] = "full",
[DEBUG_INFO_NONE] = "none",
@@ -119,9 +130,11 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
long symtab_size = get_valid_integer(json, "symtab", type, false);
const char *cpu = get_valid_string(json, "cpu", type, false);
int reloc = get_valid_string_setting(json, "reloc", type, reloc_models, 0, 5, "'none', 'pic', 'PIC', 'pie' or 'PIE'.");
int wincrt = get_valid_string_setting(json, "wincrt", type, wincrt_linking, 0, 5, "'none', 'static' or 'dynamic'.");
int x86vec = get_valid_string_setting(json, "x86vec", type, vector_capability, 0, 5, "none, mmx, sse, avx or avx512");
const char *panicfn = get_valid_string(json, "panicfn", type, false);
target->win.sdk = get_valid_string(json, "winsdk", type, false);
target->macos.sdk = get_valid_string(json, "macossdk", type, false);
target->panicfn = panicfn;
if (cc) target->cc = cc;
if (cflags) target->cflags = cflags;
@@ -129,9 +142,11 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg
if (version) target->version = version;
if (langrev) target->langrev = langrev;
if (source_dirs) target->source_dirs = source_dirs;
if (libraries) target->libraries = libraries;
if (libdirs) target->libdirs = libdirs;
if (libraries) target->libs = libraries;
if (info > -1) target->debug_info = info;
if (cpu) target->cpu = cpu;
if (wincrt > -1) target->win.crt_linking = (WinCrtLinking)wincrt;
if (reloc > -1) target->reloc_model = (RelocModel)reloc;
if (x86vec > -1) target->feature.x86_vector_capability = x86vec;
@@ -177,7 +192,7 @@ static void project_add_target(Project *project, BuildTarget *default_target, J
error_exit("More %s contained more than one target with the name %s. Please make all target names unique.", PROJECT_JSON, target->name);
}
}
type = strformat("%s %s", type, target->name);
type = str_printf("%s %s", type, target->name);
load_into_build_target(json, type, target);
}
@@ -209,6 +224,7 @@ static void project_add_targets(Project *project, JSONObject *project_data)
.feature.trap_on_wrap = false,
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
.feature.safe_mode = true,
.win.crt_linking = WIN_CRT_DEFAULT,
};
load_into_build_target(project_data, "default target", &default_target);
JSONObject *targets_json = json_obj_get(project_data, "targets");
@@ -266,7 +282,7 @@ Project *project_load(void)
{
Project *project = CALLOCS(Project);
size_t size;
char *read = read_file(PROJECT_JSON, &size);
char *read = file_read_all(PROJECT_JSON, &size);
JsonParser parser;
json_init_string(&parser, read, &malloc_arena);
JSONObject *json = json_parse(&parser);

View File

@@ -76,7 +76,7 @@ void create_project(BuildOptions *build_options)
{
char c = build_options->project_name[i];
if (c == '\0') break;
if (!is_alphanum_(c))
if (!char_is_alphanum_(c))
{
fprintf(stderr, "'%s' is not a valid project name.\n", build_options->project_name);
exit_compiler(EXIT_FAILURE);

View File

@@ -112,7 +112,7 @@ UNUSED Int128 i128_from_hexstrl(const char *str, const char *end)
while (str != end)
{
c = *(str++);
x = i128_add64(i128_shl64(x, 4), (uint64_t)hex_nibble(c));
x = i128_add64(i128_shl64(x, 4), (uint64_t)char_hex_to_nibble(c));
}
return x;
}

View File

@@ -126,14 +126,18 @@ void thread_compile_task_tb(void *compile_data)
static const char *active_target_name(void)
{
if (active_target.name) return active_target.name;
switch (active_target.arch_os_target)
{
case X86_WINDOWS:
case X64_WINDOWS:
case X64_WINDOWS_GNU:
case WINDOWS_X86:
case WINDOWS_X64:
case MINGW_X64:
if (active_target.name)
{
return str_cat(active_target.name, ".exe");
}
return "a.exe";
default:
if (active_target.name) return active_target.name;
return "a.out";
}
}
@@ -271,7 +275,7 @@ void compiler_compile(void)
for (int i = 0; i < cfiles; i++)
{
char *filename = NULL;
bool split_worked = filenamesplit(active_target.csources[i], &filename, NULL);
bool split_worked = file_namesplit(active_target.csources[i], &filename, NULL);
assert(split_worked);
size_t len = strlen(filename);
// .c -> .o (quick hack to fix the name on linux)
@@ -308,7 +312,7 @@ void compiler_compile(void)
if (create_exe)
{
const char *output_name = active_target_name();
if (active_target.arch_os_target == default_target)
if (platform_target.os != OS_TYPE_WIN32 && active_target.arch_os_target == default_target && !active_target.force_linker)
{
platform_linker(output_name, obj_files, output_file_count);
compiler_link_time = bench_mark();
@@ -327,8 +331,9 @@ void compiler_compile(void)
if (active_target.run_after_compile)
{
DEBUG_LOG("Will run");
printf("Launching %s...\n", output_name);
int ret = system(strformat("./%s", output_name));
int ret = system(platform_target.os == OS_TYPE_WIN32 ? output_name : str_printf("./%s", output_name));
printf("Program finished with exit code %d.", ret);
}
}
@@ -348,14 +353,14 @@ static const char **target_expand_source_names(const char** dirs, const char **s
{
if (name_len == 1 || name[name_len - 2] == '/')
{
char *path = copy_string(name, name_len - 1);
char *path = str_copy(name, name_len - 1);
file_add_wildcard_files(&files, path, false, suffix_list, suffix_count);
continue;
}
if (name[name_len - 2] != '*') goto INVALID_NAME;
if (name_len == 2 || name[name_len - 3] == '/')
{
char *path = copy_string(name, name_len - 2);
char *path = str_copy(name, name_len - 2);
file_add_wildcard_files(&files, path, true, suffix_list, suffix_count);
continue;
}
@@ -490,8 +495,11 @@ void print_syntax(BuildOptions *options)
}
void resolve_libraries(void);
void compile()
{
symtab_init(active_target.symtab_size);
active_target.sources = target_expand_source_names(active_target.source_dirs, c3_suffix_list, 3, true);
if (active_target.csource_dirs)
{
@@ -499,8 +507,8 @@ void compile()
active_target.csources = target_expand_source_names(active_target.csource_dirs, c_suffix_list, 1, false);
}
global_context.sources = active_target.sources;
symtab_init(active_target.symtab_size);
target_setup(&active_target);
resolve_libraries();
setup_int_define("C_SHORT_SIZE", platform_target.width_c_short, type_long);
setup_int_define("C_INT_SIZE", platform_target.width_c_int, type_long);
@@ -559,9 +567,9 @@ const char *get_object_extension(void)
{
switch (active_target.arch_os_target)
{
case X64_WINDOWS:
case X86_WINDOWS:
case X64_WINDOWS_GNU:
case WINDOWS_X64:
case WINDOWS_X86:
case MINGW_X64:
return ".obj";
default:
return ".o";
@@ -600,69 +608,11 @@ Module *compiler_find_or_create_module(Path *module_name, const char **parameter
return module;
}
void scratch_buffer_clear(void)
{
global_context.scratch_buffer_len = 0;
}
void scratch_buffer_append_len(const char *string, size_t len)
{
if (len + global_context.scratch_buffer_len > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
memcpy(global_context.scratch_buffer + global_context.scratch_buffer_len, string, len);
global_context.scratch_buffer_len += len;
}
void scratch_buffer_append(const char *string)
{
scratch_buffer_append_len(string, strlen(string));
}
void scratch_buffer_append_signed_int(int64_t i)
{
uint32_t len_needed = (uint32_t)sprintf(&global_context.scratch_buffer[global_context.scratch_buffer_len], "%lld", (long long)i);
if (global_context.scratch_buffer_len + len_needed > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
global_context.scratch_buffer_len += len_needed;
}
void scratch_buffer_append_unsigned_int(uint64_t i)
{
uint32_t len_needed = (uint32_t)sprintf(&global_context.scratch_buffer[global_context.scratch_buffer_len], "%llu", (unsigned long long)i);
if (global_context.scratch_buffer_len + len_needed > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
global_context.scratch_buffer_len += len_needed;
}
void scratch_buffer_append_char(char c)
{
if (global_context.scratch_buffer_len + 1 > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
global_context.scratch_buffer[global_context.scratch_buffer_len++] = c;
}
char *scratch_buffer_to_string(void)
{
global_context.scratch_buffer[global_context.scratch_buffer_len] = '\0';
return global_context.scratch_buffer;
}
const char *scratch_buffer_interned(void)
{
TokenType type = TOKEN_INVALID_TOKEN;
return symtab_add(global_context.scratch_buffer, global_context.scratch_buffer_len,
fnv1a(global_context.scratch_buffer, global_context.scratch_buffer_len), &type);
return symtab_add(scratch_buffer.str, scratch_buffer.len,
fnv1a(scratch_buffer.str, scratch_buffer.len), &type);
}
char *scratch_buffer_copy(void)
{
return copy_string(global_context.scratch_buffer, global_context.scratch_buffer_len);
}

View File

@@ -22,4 +22,5 @@ extern double compiler_sema_time;
extern double compiler_ir_gen_time;
extern double compiler_codegen_time;
extern double compiler_link_time;
extern const char* c3_suffix_list[3];
extern const char* c3_suffix_list[3];
extern char *arch_os_target[ARCH_OS_TARGET_LAST + 1];

View File

@@ -51,6 +51,7 @@ typedef unsigned ExprId;
typedef unsigned DeclId;
typedef unsigned TypeInfoId;
typedef struct Int128_
{
uint64_t high;
@@ -1435,9 +1436,7 @@ typedef struct
bool in_test_mode : 1;
unsigned errors_found;
unsigned warnings_found;
char scratch_buffer[MAX_STRING_BUFFER];
Decl ***locals_list;
uint32_t scratch_buffer_len;
HTable compiler_defines;
Module std_module;
DeclTable symbols;
@@ -1554,6 +1553,7 @@ typedef struct
} NameResolve;
extern GlobalContext global_context;
extern BuildTarget active_target;
extern Ast *poisoned_ast;
@@ -1989,15 +1989,7 @@ void decltable_init(DeclTable *table, uint32_t initial_size);
DeclId decltable_get(DeclTable *table, const char *name);
void decltable_set(DeclTable *table, Decl *decl);
void scratch_buffer_clear(void);
void scratch_buffer_append(const char *string);
void scratch_buffer_append_len(const char *string, size_t len);
void scratch_buffer_append_char(char c);
void scratch_buffer_append_signed_int(int64_t i);
UNUSED void scratch_buffer_append_unsigned_int(uint64_t i);
char *scratch_buffer_to_string(void);
const char *scratch_buffer_interned(void);
char *scratch_buffer_copy(void);
const char *symtab_add(const char *symbol, uint32_t len, uint32_t fnv1hash, TokenType *type);
const char *symtab_find(const char *symbol, uint32_t len, uint32_t fnv1hash, TokenType *type);
@@ -2005,13 +1997,15 @@ void *llvm_target_machine_create(void);
void target_setup(BuildTarget *build_target);
int target_alloca_addr_space();
const char *macos_sysroot(void);
MacSDK *macos_sysroot_sdk_information(const char *sdk_path);
WindowsSDK *windows_get_sdk(void);
void c_abi_func_create(FunctionPrototype *proto);
bool token_is_any_type(TokenType type);
const char *token_type_to_string(TokenType type);
AlignSize type_abi_alignment(Type *type);
AlignSize type_alloca_alignment(Type *type);
@@ -2486,6 +2480,7 @@ bool obj_format_linking_supported(ObjectFormatType format_type);
bool linker(const char *output_file, const char **files, unsigned file_count);
void platform_linker(const char *output_file, const char **files, unsigned file_count);
void platform_compiler(const char **files, unsigned file_count, const char* flags);
const char *arch_to_linker_arch(ArchType arch);
#define CAT(a,b) CAT2(a,b) // force expand
#define CAT2(a,b) a##b // actually concatenate

View File

@@ -66,9 +66,9 @@ static bool filename_to_module_in_buffer(const char *path)
for (int i = last_slash + 1; i < last_dot; i++)
{
char c = path[i];
if (is_letter(c) || is_digit(c))
if (char_is_letter(c) || char_is_digit(c))
{
c = (char)(is_upper(c) ? c + 'a' - 'A' : c);
c = (char)(char_is_upper(c) ? c + 'a' - 'A' : c);
}
else
{
@@ -89,9 +89,9 @@ bool context_set_module_from_filename(ParseContext *context)
}
TokenType type = TOKEN_IDENT;
const char *module_name = symtab_add(global_context.scratch_buffer,
global_context.scratch_buffer_len,
fnv1a(global_context.scratch_buffer, (uint32_t) global_context.scratch_buffer_len),
const char *module_name = symtab_add(scratch_buffer.str,
scratch_buffer.len,
fnv1a(scratch_buffer.str, (uint32_t) scratch_buffer.len),
&type);
if (type != TOKEN_IDENT)
@@ -103,14 +103,14 @@ bool context_set_module_from_filename(ParseContext *context)
Path *path = CALLOCS(Path);
path->span = INVALID_SPAN;
path->module = module_name;
path->len = global_context.scratch_buffer_len;
path->len = scratch_buffer.len;
return create_module_or_check_name(context->unit, path, NULL, true);
}
bool context_set_module(ParseContext *context, Path *path, const char **generic_parameters, bool is_private)
{
// Note that we allow the illegal name for now, to be able to parse further.
if (!is_all_lower(path->module))
if (!str_has_no_uppercase(path->module))
{
SEMA_ERROR(path, "A module name may not have any upper case characters.");
return false;
@@ -277,8 +277,7 @@ bool unit_add_import(CompilationUnit *unit, Path *path, bool private_import)
{
DEBUG_LOG("SEMA: Add import of '%s'.", path->module);
if (!is_all_lower(path->module))
if (!str_has_no_uppercase(path->module))
{
SEMA_ERROR(path, "A module is not expected to have any upper case characters, please change it.");
return false;

View File

@@ -66,7 +66,7 @@ static void print_error(SourceSpan location, const char *message, PrintType prin
{
current += row_len + 1;
row_len = 0;
while (current[row_len] != '\n') row_len++;
while (current[row_len] != '\n' && current[row_len]) row_len++;
if (row_len > max_lines_for_display)
{
eprintf(number_buffer_elided, row, max_lines_for_display - 1, current);
@@ -148,15 +148,7 @@ static void print_error(SourceSpan location, const char *message, PrintType prin
static void vprint_error(SourceSpan location, const char *message, va_list args)
{
#define MAX_ERROR_LEN 4096
char buffer[MAX_ERROR_LEN];
size_t written = vsnprintf(buffer, MAX_ERROR_LEN - 1, message, args);
if (written > MAX_ERROR_LEN - 2)
{
print_error(location, "<Error message was too long>", PRINT_TYPE_ERROR);
return;
}
print_error(location, buffer, PRINT_TYPE_ERROR);
print_error(location, str_vprintf(message, args), PRINT_TYPE_ERROR);
}
@@ -251,7 +243,7 @@ const char *span_to_string(SourceSpan span)
}
assert(row == row_to_find);
const char *start = current + col - 1;
return copy_string(start, length);
return str_copy(start, length);
}

View File

@@ -178,7 +178,7 @@ Float float_from_string(const char *string, char **error)
if (error) *error = err_float_out_of_range;
return (Float){ .type = TYPE_POISONED };
}
char *expected_end = global_context.scratch_buffer + global_context.scratch_buffer_len;
char *expected_end = scratch_buffer.str + scratch_buffer.len;
if (d == 0 && end != expected_end)
{
if (error) *error = err_float_format_invalid;
@@ -200,7 +200,7 @@ Float float_from_hex(const char *string, char **error)
char c;
scratch_buffer_clear();
scratch_buffer_append("0x");
while ((c = *(index++)) && (c == '_' || is_hex(c)))
while ((c = *(index++)) && (c == '_' || char_is_hex(c)))
{
if (c == '_') continue;
scratch_buffer_append_char(c);
@@ -208,7 +208,7 @@ Float float_from_hex(const char *string, char **error)
if (c == '.')
{
scratch_buffer_append_char(c);
while ((c = *(index++)) && (c == '_' || is_hex(c)))
while ((c = *(index++)) && (c == '_' || char_is_hex(c)))
{
if (c == '_') continue;
scratch_buffer_append_char(c);
@@ -271,7 +271,7 @@ Float float_from_hex(const char *string, char **error)
if (error) *error = err_float_out_of_range;
return (Float){ .type = TYPE_POISONED };
}
if (d == 0 && end != global_context.scratch_buffer + global_context.scratch_buffer_len)
if (d == 0 && end != scratch_buffer.str + scratch_buffer.len)
{
if (error) *error = err_float_format_invalid;
return (Float){ .type = TYPE_POISONED };

View File

@@ -227,7 +227,7 @@ void header_gen(Module *module)
{
TODO
CompilationUnit *unit = module->units[0];
const char *filename = strcat_arena(unit->file->name, ".h");
const char *filename = str_cat(unit->file->name, ".h");
FILE *file = fopen(filename, "w");
OUTPUT("#include <stdint.h>\n");
OUTPUT("#ifndef __c3__\n");

View File

@@ -378,7 +378,7 @@ static inline bool scan_ident(Lexer *lexer, TokenType normal, TokenType const_to
static bool scan_number_suffix(Lexer *lexer, bool *is_float)
{
char c = peek(lexer);
if (!is_alphanum_(c)) return true;
if (!char_is_alphanum_(c)) return true;
switch (c)
{
case 'u':
@@ -390,17 +390,17 @@ static bool scan_number_suffix(Lexer *lexer, bool *is_float)
return add_error_token_at_current(lexer, "Integer suffix '%c' is not valid for a floating point literal.", c);
}
next(lexer);
while (is_number(c = peek(lexer))) next(lexer);
while (char_is_digit(c = peek(lexer))) next(lexer);
break;
case 'f':
next(lexer);
*is_float = true;
while (is_number(c = peek(lexer))) next(lexer);
while (char_is_digit(c = peek(lexer))) next(lexer);
break;
default:
break;
}
if (is_alphanum_(c))
if (char_is_alphanum_(c))
{
next(lexer);
return add_error_token(lexer, "This doesn't seem to be a valid literal.");
@@ -414,13 +414,13 @@ static bool scan_number_suffix(Lexer *lexer, bool *is_float)
*/
static bool scan_oct(Lexer *lexer)
{
if (!is_oct(peek(lexer)))
if (!char_is_oct(peek(lexer)))
{
return add_error_token_at_current(lexer, "An expression starting with '0o' should be followed by octal numbers (0-7).");
}
next(lexer);
while (is_oct_or_(peek(lexer))) next(lexer);
if (is_number(peek(lexer)))
while (char_is_oct_or_(peek(lexer))) next(lexer);
if (char_is_digit(peek(lexer)))
{
return add_error_token_at_current(lexer, "An expression starting with '0o' should be followed by octal numbers (0-7).");
}
@@ -438,13 +438,13 @@ static bool scan_oct(Lexer *lexer)
**/
static bool scan_binary(Lexer *lexer)
{
if (!is_binary(peek(lexer)))
if (!char_is_binary(peek(lexer)))
{
return add_error_token_at_current(lexer, "An expression starting with '0b' should be followed by binary digits (0-1).");
}
next(lexer);
while (is_binary_or_(peek(lexer))) next(lexer);
if (is_number(peek((lexer))))
while (char_is_binary_or_(peek(lexer))) next(lexer);
if (char_is_digit(peek((lexer))))
{
return add_error_token_at_current(lexer, "An expression starting with '0b' should be followed by binary digits (0-1).");
}
@@ -475,7 +475,7 @@ static inline bool scan_exponent(Lexer *lexer)
next(lexer);
}
// Now we need at least one digit
if (!is_digit(c))
if (!char_is_digit(c))
{
if (c == 0)
{
@@ -487,7 +487,7 @@ static inline bool scan_exponent(Lexer *lexer)
return add_error_token(lexer, "Parsing the floating point exponent failed, because '%c' is not a number.", c);
}
// Walk through all of the digits.
while (is_digit(peek(lexer))) next(lexer);
while (char_is_digit(peek(lexer))) next(lexer);
return true;
}
@@ -497,12 +497,12 @@ static inline bool scan_exponent(Lexer *lexer)
**/
static inline bool scan_hex(Lexer *lexer)
{
if (!is_hex(peek(lexer)))
if (!char_is_hex(peek(lexer)))
{
return add_error_token_at_current(lexer, "'0x' starts a hexadecimal number, so the next character should be 0-9, a-f or A-F.");
}
next(lexer);
while (is_hex_or_(peek(lexer))) next(lexer);
while (char_is_hex_or_(peek(lexer))) next(lexer);
bool is_float = false;
if (peek(lexer) == '.' && peek_next(lexer) != '.')
{
@@ -510,8 +510,8 @@ static inline bool scan_hex(Lexer *lexer)
next(lexer);
char c = peek(lexer);
if (c == '_') return add_error_token_at_current(lexer, "'_' is not allowed directly after decimal point, try removing it.");
if (is_hex(c)) next(lexer);
while (is_hex_or_(peek(lexer))) next(lexer);
if (char_is_hex(c)) next(lexer);
while (char_is_hex_or_(peek(lexer))) next(lexer);
}
char c = peek(lexer);
if (c == 'p' || c == 'P')
@@ -533,11 +533,11 @@ static inline bool scan_hex(Lexer *lexer)
*/
static inline bool scan_dec(Lexer *lexer)
{
assert(is_digit(peek(lexer)));
assert(char_is_digit(peek(lexer)));
// Walk through the digits, we don't need to worry about
// initial _ because we only call this if we have a digit initially.
while (is_digit_or_(peek(lexer))) next(lexer);
while (char_is_digit_or_(peek(lexer))) next(lexer);
// Assume no float.
bool is_float = false;
@@ -555,7 +555,7 @@ static inline bool scan_dec(Lexer *lexer)
if (c == '_') return add_error_token_at_current(lexer, "'_' is not allowed directly after decimal point, try removing it.");
// Now walk until we see no more digits.
// This allows 123. as a floating point number.
while (is_digit_or_(peek(lexer))) next(lexer);
while (char_is_digit_or_(peek(lexer))) next(lexer);
}
char c = peek(lexer);
// We might have an exponential. We allow 123e1 and 123.e1 as floating point, so
@@ -619,7 +619,7 @@ static inline int64_t scan_hex_literal(Lexer *lexer, int positions)
for (int j = 0; j < positions; j++)
{
hex <<= 4U;
int i = char_to_nibble(peek(lexer));
int i = char_hex_to_nibble(peek(lexer));
if (i < 0)
{
return -1;
@@ -739,7 +739,7 @@ static inline bool scan_char(Lexer *lexer)
{
assert(c == '\\');
c = peek(lexer);
escape = is_valid_escape(c);
escape = char_is_valid_escape(c);
if (escape == -1)
{
lexer->lexing_start += 1;
@@ -826,15 +826,15 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
{
int scanned;
uint64_t unicode_char;
signed char scanned_char = is_valid_escape(src[0]);
signed char scanned_char = char_is_valid_escape(src[0]);
if (scanned_char < 0) return -1;
switch (scanned_char)
{
case 'x':
{
int h = char_to_nibble(src[1]);
int h = char_hex_to_nibble(src[1]);
if (h < 0) return -1;
int l = char_to_nibble(src[2]);
int l = char_hex_to_nibble(src[2]);
if (l < 0) return -1;
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
scanned = 3;
@@ -842,13 +842,13 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
}
case 'u':
{
int x1 = char_to_nibble(src[1]);
int x1 = char_hex_to_nibble(src[1]);
if (x1 < 0) return -1;
int x2 = char_to_nibble(src[2]);
int x2 = char_hex_to_nibble(src[2]);
if (x2 < 0) return -1;
int x3 = char_to_nibble(src[3]);
int x3 = char_hex_to_nibble(src[3]);
if (x3 < 0) return -1;
int x4 = char_to_nibble(src[4]);
int x4 = char_hex_to_nibble(src[4]);
if (x4 < 0) return -1;
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
scanned = 5;
@@ -856,21 +856,21 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
}
case 'U':
{
int x1 = char_to_nibble(src[1]);
int x1 = char_hex_to_nibble(src[1]);
if (x1 < 0) return -1;
int x2 = char_to_nibble(src[2]);
int x2 = char_hex_to_nibble(src[2]);
if (x2 < 0) return -1;
int x3 = char_to_nibble(src[3]);
int x3 = char_hex_to_nibble(src[3]);
if (x3 < 0) return -1;
int x4 = char_to_nibble(src[4]);
int x4 = char_hex_to_nibble(src[4]);
if (x4 < 0) return -1;
int x5 = char_to_nibble(src[5]);
int x5 = char_hex_to_nibble(src[5]);
if (x5 < 0) return -1;
int x6 = char_to_nibble(src[6]);
int x6 = char_hex_to_nibble(src[6]);
if (x6 < 0) return -1;
int x7 = char_to_nibble(src[7]);
int x7 = char_hex_to_nibble(src[7]);
if (x7 < 0) return -1;
int x8 = char_to_nibble(src[8]);
int x8 = char_hex_to_nibble(src[8]);
if (x8 < 0) return -1;
unicode_char = ((unsigned) x1 << 28U) + ((unsigned) x2 << 24U) + ((unsigned) x3 << 20U) + ((unsigned) x4 << 16U) +
((unsigned) x5 << 12U) + ((unsigned) x6 << 8U) + ((unsigned) x7 << 4U) + (unsigned)x8;
@@ -1031,13 +1031,13 @@ static inline bool scan_hex_array(Lexer *lexer)
return add_error_token_at_current(lexer, "The hex string seems to be missing a terminating '%c'", start_char);
}
if (c == start_char) break;
if (is_hex(c))
if (char_is_hex(c))
{
next(lexer);
len++;
continue;
}
if (is_whitespace(c))
if (char_is_whitespace(c))
{
next(lexer);
continue;
@@ -1080,7 +1080,7 @@ static inline bool scan_base64(Lexer *lexer)
}
next(lexer);
if (c == start_char) break;
if (is_base64(c))
if (char_is_base64(c))
{
if (end_len)
{
@@ -1098,7 +1098,7 @@ static inline bool scan_base64(Lexer *lexer)
end_len++;
continue;
}
if (!is_whitespace(c))
if (!char_is_whitespace(c))
{
if (c < ' ' || c > 127)
{
@@ -1297,7 +1297,7 @@ static bool lexer_scan_token_inner(Lexer *lexer)
case '$':
if (match(lexer, '$'))
{
if (is_letter(peek(lexer)))
if (char_is_letter(peek(lexer)))
{
return return_token(lexer, TOKEN_BUILTIN, "$$");
}

190
src/compiler/libraries.c Normal file
View File

@@ -0,0 +1,190 @@
#include "compiler_internal.h"
#include "../utils/json.h"
#define MANIFEST_FILE "manifest.json"
static inline JSONObject *get_mandatory(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = json_obj_get(object, key);
if (!value) error_exit("The mandatory '%s' field was missing in '%s'.", library->dir);
return value;
}
static inline const char *get_mandatory_string(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = get_mandatory(library, object, key);
if (value->type != J_STRING) error_exit("Expected string value for '%s' in '%s'.", library->dir);
return value->str;
}
static inline JSONObject *get_optional_string_array(Library *library, JSONObject *object, const char *key)
{
JSONObject *value = json_obj_get(object, key);
if (!value) return NULL;
if (value->type != J_ARRAY) error_exit("Expected an array value for '%s' in '%s'.", library->dir);
for (int i = 0; i < value->array_len; i++)
{
JSONObject *val = value->elements[i];
if (val->type != J_STRING) error_exit("Expected only strings in array '%s' in '%s'.", library->dir);
}
return value;
}
static inline const char **get_optional_string_array_as_array(Library *library, JSONObject *object, const char *key)
{
JSONObject *array = get_optional_string_array(library, object, key);
if (!array || !array->array_len) return NULL;
const char **array_result = VECNEW(const char*, array->array_len);
for (size_t i = 0; i < array->array_len; i++)
{
vec_add(array_result, array->elements[i]->str);
}
return array_result;
}
static inline void parse_provides(Library *library, JSONObject *object)
{
const char *provides = get_mandatory_string(library, object, "provides");
if (!str_is_valid_lowercase_name(provides))
{
char *res = strdup(provides);
str_ellide_in_place(res, 32);
error_exit("Invalid 'provides' module name in %s, was '%s'.", library->dir, json_obj_get(object, "provides")->str);
}
library->provides = provides;
}
static inline void parse_depends(Library *library, JSONObject *object)
{
JSONObject *depends = get_optional_string_array(library, object, "depends");
if (!depends) return;
TODO
}
static inline void parse_library_target(Library *library, LibraryTarget *target, JSONObject *object)
{
target->link_flags = get_optional_string_array_as_array(library, object, "linkflags");
target->linked_libs = get_optional_string_array_as_array(library, object, "linked-libs");
target->depends = get_optional_string_array_as_array(library, object, "depends");
}
static inline void parse_library_type(Library *library, LibraryTarget ***target_group, JSONObject *object)
{
if (!object) return;
if (object->type != J_OBJECT) error_exit("Expected a set of targets in %s.", library->dir);
for (size_t i = 0; i < object->member_len; i++)
{
JSONObject *member = object->members[i];
const char *key = object->keys[i];
if (member->type != J_OBJECT) error_exit("Expected a list of properties for a target in %s.", library->dir);
LibraryTarget *library_target = CALLOCS(LibraryTarget);
ArchOsTarget target = arch_os_target_from_string(key);
if (target == ARCH_OS_TARGET_DEFAULT)
{
error_exit("Invalid arch/os '%s' in %s.", key, library->dir);
}
library_target->arch_os = target;
vec_add(*target_group, library_target);
parse_library_target(library, library_target, member);
}
}
static Library *add_library(JSONObject *object, const char *dir)
{
Library *library = CALLOCS(Library);
library->dir = dir;
parse_provides(library, object);
parse_depends(library, object);
parse_library_type(library, &library->targets, json_obj_get(object, "targets"));
return library;
}
static Library *find_library(Library **libs, size_t lib_count, const char *name)
{
for (size_t i = 0; i < lib_count; i++)
{
if (strcmp(libs[i]->provides, name) == 0)
{
return libs[i];
break;
}
}
error_exit("Required library '%s' could not be found.\n", name);
}
static void add_library_dependency(Library *library, Library **library_list, size_t lib_count)
{
if (library->target_used) return;
LibraryTarget *target_found = NULL;
VECEACH(library->targets, j)
{
LibraryTarget *target = library->targets[j];
if (target->arch_os == active_target.arch_os_target)
{
target_found = target;
break;
}
}
if (!target_found)
{
error_exit("Library '%s' cannot be used with arch/os '%s'.", library->provides, arch_os_target[active_target.arch_os_target]);
}
library->target_used = target_found;
VECEACH(library->depends, i)
{
add_library_dependency(find_library(library_list, lib_count, library->depends[i]), library_list, lib_count);
}
VECEACH(target_found->depends, i)
{
add_library_dependency(find_library(library_list, lib_count, target_found->depends[i]),
library_list,
lib_count);
}
}
void resolve_libraries(void)
{
static const char *c3lib_suffix = ".c3l";
const char **c3_libs = NULL;
VECEACH(active_target.libdirs, i)
{
file_add_wildcard_files(&c3_libs, active_target.libdirs[i], false, &c3lib_suffix, 1);
}
JsonParser parser;
Library *libraries[MAX_LIB_DIRS * 2];
size_t lib_count = 0;
VECEACH(c3_libs, i)
{
size_t size;
const char *lib = c3_libs[i];
if (!file_is_dir(lib))
{
error_exit("Packaged .c3l are not supported yet.");
}
const char *manifest_path = file_append_path(lib, MANIFEST_FILE);
char *read = file_read_all(manifest_path, &size);
json_init_string(&parser, read, &malloc_arena);
JSONObject *json = json_parse(&parser);
if (parser.error_message)
{
error_exit("Error on line %d reading '%s':'%s'", parser.line, manifest_path, parser.error_message);
}
if (lib_count == MAX_LIB_DIRS * 2) error_exit("Too many libraries added, exceeded %d.", MAX_LIB_DIRS * 2);
libraries[lib_count++] = add_library(json, lib);
}
VECEACH(active_target.libs, i)
{
const char *lib_name = active_target.libs[i];
add_library_dependency(find_library(libraries, lib_count, lib_name), libraries, lib_count);
}
for (size_t i = 0; i < lib_count; i++)
{
Library *library = libraries[i];
LibraryTarget *target = library->target_used;
if (!target) continue;
file_add_wildcard_files(&active_target.sources, library->dir, false, c3_suffix_list, 3);
vec_add(active_target.library_list, library);
vec_add(active_target.linker_libdirs, file_append_path(library->dir, arch_os_target[active_target.arch_os_target]));
}
}

View File

@@ -2,12 +2,6 @@
#include <llvm/Config/llvm-config.h> // for LLVM_VERSION_STRING
#ifdef PLATFORM_WINDOWS
#include "utils/find_msvc.h"
#endif
extern bool llvm_link_elf(const char **args, int arg_count, const char **error_string);
extern bool llvm_link_macho(const char **args, int arg_count, const char **error_string);
extern bool llvm_link_coff(const char **args, int arg_count, const char **error_string);
@@ -27,29 +21,181 @@ static const char *join_strings(const char **args, unsigned count)
char *res = "";
for (unsigned i = 0; i < count; ++i)
{
res = strcat_arena(res, args[i]);
res = str_cat(res, args[i]);
}
return res;
}
static void prepare_msys2_linker_flags(const char ***args, const char **files_to_link, unsigned file_count)
typedef enum
{
LINKER_LINK_EXE,
LINKER_LD,
LINKER_LD64,
LINKER_WASM,
LINKER_CC,
} LinkerType;
#define add_arg(arg_) vec_add(*args_ref, (arg_))
#define add_arg2(arg_, arg_2) vec_add(*args_ref, str_cat((arg_), (arg_2)))
static inline bool is_no_pie(RelocModel reloc)
{
return reloc == RELOC_NONE;
}
static inline bool is_pie(RelocModel reloc)
{
return reloc == RELOC_BIG_PIE || reloc == RELOC_BIG_PIE;
}
static const char *ld_target(ArchType arch_type)
{
switch (platform_target.arch)
{
case ARCH_TYPE_X86_64:
return "elf_x86_64";
case ARCH_TYPE_X86:
return "elf_i386";
case ARCH_TYPE_AARCH64:
return "aarch64elf";
case ARCH_TYPE_RISCV32:
return "elf32lriscv";
case ARCH_TYPE_RISCV64:
return "elf64lriscv";
default:
error_exit("Architecture currently not available for cross linking.");
}
}
static const char *string_esc(const char *str)
{
scratch_buffer_clear();
size_t len = strlen(str);
for (size_t i = 0; i < len; i++)
{
if (i > 3 && !char_is_alphanum_(str[i])) scratch_buffer_append_char('\\');
scratch_buffer_append_char(str[i]);
}
return strdup(scratch_buffer_to_string());
}
static void linker_setup_windows(const char ***args_ref, LinkerType linker_type)
{
if (linker_type == LINKER_CC) return;
//add_arg("/MACHINE:X64");
if (active_target.win.sdk)
{
add_arg(str_printf("/LIBPATH:%s", active_target.win.sdk));
}
else
{
WindowsSDK *windows_sdk = windows_get_sdk();
if (!windows_sdk) error_exit("Windows applications cannot be cross compiled without --winsdk.");
if (!file_is_dir(windows_sdk->vs_library_path)) error_exit("Failed to find windows sdk.");
add_arg(str_printf("/LIBPATH:%s", windows_sdk->windows_sdk_um_library_path));
add_arg(str_printf("/LIBPATH:%s", windows_sdk->windows_sdk_ucrt_library_path));
add_arg(str_printf("/LIBPATH:%s", windows_sdk->vs_library_path));
}
// Do not link any.
if (active_target.win.crt_linking == WIN_CRT_NONE) return;
add_arg("kernel32.lib");
add_arg("ntdll.lib");
add_arg("legacy_stdio_definitions.lib");
if (active_target.win.crt_linking == WIN_CRT_STATIC)
{
add_arg("libucrt.lib");
add_arg("libvcruntimed.lib");
add_arg("libcmt.lib");
add_arg("libcpmt.lib");
}
else
{
add_arg("ucrt.lib");
add_arg("vcruntime.lib");
add_arg("msvcrt.lib");
add_arg("msvcprt.lib");
}
add_arg("/NOLOGO");
}
#ifdef mingw64_support
static void linker_setup_mingw64_gcc(const char ***args_ref)
{
const char *root = getenv("MSYSTEM_PREFIX");
#define add_arg(opt) vec_add(*args, opt)
add_arg("-m");
add_arg("i386pep");
add_arg("-Bdynamic");
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crt2.o" }, 2));
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crtbegin.o" }, 2));
add_arg(join_strings((const char *[]){ "-L", root, "\\x86_64-w64-mingw32\\lib" }, 3));
add_arg(join_strings((const char *[]){ "-L", root, "\\lib" }, 3));
add_arg(join_strings((const char *[]){ "-L", root, "\\x86_64-w64-mingw32\\sys-root\\mingw\\lib" }, 3));
add_arg(join_strings((const char *[]){ "-L", root, "\\lib\\clang\\", LLVM_VERSION_STRING, "\\lib\\windows" }, 5));
add_files(args, files_to_link, file_count);
const char *root = getenv("MSYSTEM_PREFIX");
const char *gcc_base = strformat("%s/lib/gcc/x86_64-w64-mingw32", root);
if (!file_exists(gcc_base)) error_exit("Missing GCC");
const char *name = file_first(gcc_base);
const char *gcc_path = strformat("%s/%s/", gcc_base, name);
add_arg(strformat("-L%s/x86_64-w64-mingw32/lib", root));
add_arg(strformat("-L%s/lib", root));
add_arg2(gcc_path, "crtbegin.o");
add_arg(strformat("%s/lib/crt2.o", root));
add_arg(strformat("%s/lib/default-manifest.o", root));
add_arg2("-L", gcc_path);
add_arg("-lkernel32");
add_arg("-lmingw32");
add_arg(join_strings((const char *[]){ root, "\\lib\\clang\\", LLVM_VERSION_STRING,
"\\lib\\windows\\libclang_rt.builtins-x86_64.a" }, 4));
add_arg("-lunwind");
add_arg("-lgcc");
add_arg("-lgcc_eh");
add_arg("-lmoldname");
add_arg("-lmingwex");
add_arg("-lmsvcrt");
add_arg("-ladvapi32");
add_arg("-lshell32");
add_arg("-luser32");
add_arg("-lpthread");
add_arg2(gcc_path, "crtend.o");
}
static void linker_setup_windows_gnu(const char ***args_ref, LinkerType linker_type)
{
if (linker_type == LINKER_CC) return;
bool is_clang = strcmp(getenv("MSYSTEM"), "CLANG64") == 0;
bool is_mingw = strcmp(getenv("MSYSTEM"), "MINGW64") == 0;
if (!is_clang && !is_mingw)
{
error_exit("Crosslinking MSYS is not yet supported.");
}
if (is_mingw)
{
linker_setup_mingw64_gcc(args_ref);
return;
}
const char *root = getenv("MSYSTEM_PREFIX");
const char *compiler_prefix;
if (is_clang)
{
char *filename;
char *dir;
path_get_dir_and_filename_from_full(root, &filename, &dir);
compiler_prefix = filename;
root = dir;
}
else
{
compiler_prefix = "x86_64-w64-mingw32";
}
add_arg("-m");
add_arg("i386pep");
add_arg("-Bdynamic");
const char *lib = strformat("%s/%s/lib", root, compiler_prefix);
if (!file_exists(lib))
{
error_exit("Cannot find '%s'.", lib);
}
add_arg2(lib, "/crt2.o");
add_arg2(lib, "/crtbegin.o");
add_arg2("-L", lib);
add_arg(strformat("-L%s/lib", root));
add_arg(strformat("-L%s/%s/sys-root/mingw/lib", root, compiler_prefix));
const char *clang_dir = strformat("%s/lib/clang/" LLVM_VERSION_STRING, root);
add_arg(strformat("-L%s/lib/windows", clang_dir));
add_arg("-lmingw32");
add_arg(strformat("%s/lib/windows/libclang_rt.builtins-x86_64.a", clang_dir));
add_arg("-lmoldname");
add_arg("-lmingwex");
add_arg("-lmsvcrt");
@@ -58,36 +204,179 @@ static void prepare_msys2_linker_flags(const char ***args, const char **files_to
add_arg("-luser32");
add_arg("-lkernel32");
add_arg("-lmingw32");
add_arg(join_strings((const char *[]){ root, "\\lib\\clang\\", LLVM_VERSION_STRING,
"\\lib\\windows\\libclang_rt.builtins-x86_64.a" }, 4));
add_arg("-lunwind");
add_arg("-lmoldname");
add_arg("-lmingwex");
add_arg("-lmsvcrt");
add_arg("-lkernel32");
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crtend.o" }, 2));
#undef add_arg
add_arg2(lib, "\\crtend.o");
}
*/
#endif
static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
{
if (linker_type == LINKER_CC) return;
const char *sysroot = active_target.macos.sdk ? active_target.macos.sdk : macos_sysroot();
if (!sysroot)
{
error_exit("Cannot crosslink MacOS without providing --macossdk.");
}
DEBUG_LOG("Macos SDK: %s", sysroot);
MacSDK *mac_sdk = macos_sysroot_sdk_information(sysroot);
add_arg("-arch");
add_arg(arch_to_linker_arch(platform_target.arch));
add_arg("-lSystem");
add_arg("-lm");
add_arg("-syslibroot");
add_arg(sysroot);
if (is_no_pie(platform_target.reloc_model)) add_arg("-no_pie");
if (is_pie(platform_target.reloc_model)) add_arg("-pie");
add_arg("-platform_version");
add_arg("macos");
add_arg(str_printf("%d.0.0", mac_sdk->macos_deploy_target.major));
add_arg(str_printf("%d.%d", mac_sdk->macos_deploy_target.major, mac_sdk->macos_deploy_target.minor));
}
static void append_linker_pie_options(RelocModel reloc, const char ***args_ref)
static const char *find_linux_crt(void)
{
switch (reloc)
if (file_exists("/usr/lib/x86_64-linux-gnu/crt1.o"))
{
case RELOC_DEFAULT:
UNREACHABLE
case RELOC_NONE:
vec_add(*args_ref, "-no_pie");
break;
case RELOC_SMALL_PIC:
case RELOC_BIG_PIC:
break;
case RELOC_SMALL_PIE:
case RELOC_BIG_PIE:
vec_add(*args_ref, "-pie");
break;
return "/usr/lib/x86_64-linux-gnu/";
}
return NULL;
}
static const char *find_linux_crt_begin(void)
{
if (file_exists("/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o"))
{
return "/usr/lib/gcc/x86_64-linux-gnu/10/";
}
return NULL;
}
static void linker_setup_linux(const char ***args_ref, LinkerType linker_type)
{
if (linker_type == LINKER_CC) return;
if (is_no_pie(platform_target.reloc_model)) add_arg("-no-pie");
if (is_pie(platform_target.reloc_model)) add_arg("-pie");
if (platform_target.arch == ARCH_TYPE_X86_64) add_arg("--eh-frame-hdr");
const char *crt_begin_dir = find_linux_crt_begin();
const char *crt_dir = find_linux_crt();
if (!crt_begin_dir || !crt_dir)
{
error_exit("Failed to find the C runtime at link time.");
}
if (is_pie_pic(platform_target.reloc_model))
{
add_arg("-pie");
add_arg2(crt_dir, "Scrt1.o");
add_arg2(crt_begin_dir, "crtbeginS.o");
add_arg2(crt_dir, "crti.o");
add_arg2(crt_begin_dir, "crtendS.o");
}
else
{
add_arg2(crt_dir, "crt1.o");
add_arg2(crt_begin_dir, "crtbegin.o");
add_arg2(crt_dir, "crti.o");
add_arg2(crt_begin_dir, "crtend.o");
}
add_arg2(crt_dir, "crtn.o");
add_arg2("-L", crt_dir);
add_arg("--dynamic-linker=/lib64/ld-linux-x86-64.so.2");
add_arg("-lc");
add_arg("-lm");
add_arg("-L/usr/lib/");
add_arg("-L/lib/");
add_arg("-m");
add_arg(ld_target(platform_target.arch));
}
static bool linker_setup(const char ***args_ref, const char **files_to_link, unsigned file_count,
const char *output_file, LinkerType linker_type)
{
bool use_win = linker_type == LINKER_LINK_EXE;
if (use_win)
{
add_arg2("/OUT:", output_file);
}
else
{
add_arg("-o");
add_arg(output_file);
}
const char *lib_path_opt = use_win ? "/LIBPATH:" : "-L";
switch (platform_target.os)
{
case OS_UNSUPPORTED:
UNREACHABLE
case OS_TYPE_WIN32:
linker_setup_windows(args_ref, linker_type);
break;
case OS_TYPE_MACOSX:
linker_setup_macos(args_ref, linker_type);
break;
case OS_TYPE_WATCHOS:
case OS_TYPE_IOS:
case OS_TYPE_OPENBSD:
case OS_TYPE_NETBSD:
case OS_TYPE_TVOS:
case OS_TYPE_FREE_BSD:
return false;
case OS_TYPE_WASI:
return false;
case OS_TYPE_LINUX:
linker_setup_linux(args_ref, linker_type);
break;
case OS_TYPE_UNKNOWN:
error_exit("Linking is not supported for unknown OS.");
case OS_TYPE_NONE:
error_exit("Linking is not supported for freestanding.");
}
for (unsigned i = 0; i < file_count; i++)
{
add_arg(files_to_link[i]);
}
VECEACH(active_target.linker_libdirs, i)
{
add_arg2(lib_path_opt, active_target.linker_libdirs[i]);
}
VECEACH(active_target.link_args, i)
{
add_arg(active_target.link_args[i]);
}
VECEACH(active_target.library_list, i)
{
Library *library = active_target.library_list[i];
LibraryTarget *target = library->target_used;
VECEACH(target->link_flags, j)
{
add_arg(target->link_flags[j]);
}
VECEACH(target->linked_libs, j)
{
const char *lib = target->linked_libs[j];
const char *framework = str_remove_suffix(lib, ".framework");
if (framework)
{
add_arg("-framework");
add_arg(framework);
continue;
}
if (use_win)
{
add_arg2(lib, ".lib");
}
else
{
add_arg2("-l", lib);
}
}
}
return true;
}
#undef add_arg2
#undef add_arg
static void append_fpie_pic_options(RelocModel reloc, const char ***args_ref)
{
switch (reloc)
@@ -117,166 +406,57 @@ static void append_fpie_pic_options(RelocModel reloc, const char ***args_ref)
}
}
LinkerType linker_find_linker_type(void)
{
switch (platform_target.os)
{
case OS_UNSUPPORTED:
case OS_TYPE_UNKNOWN:
case OS_TYPE_NONE:
case OS_TYPE_FREE_BSD:
case OS_TYPE_LINUX:
case OS_TYPE_NETBSD:
case OS_TYPE_OPENBSD:
return LINKER_LD;
case OS_TYPE_IOS:
case OS_TYPE_MACOSX:
case OS_TYPE_TVOS:
case OS_TYPE_WATCHOS:
return LINKER_LD64;
case OS_TYPE_WIN32:
return LINKER_LINK_EXE;
case OS_TYPE_WASI:
return LINKER_WASM;
}
UNREACHABLE
}
static bool link_exe(const char *output_file, const char **files_to_link, unsigned file_count)
{
DEBUG_LOG("Using linker directly.");
const char **args = NULL;
#ifdef _MSC_VER
if (platform_target.os == OS_TYPE_WIN32)
{
vec_add(args, join_strings((const char* []) {"/out:", output_file}, 2));
}
else
{
#endif
vec_add(args, "-o");
vec_add(args, output_file);
#ifdef _MSC_VER
}
#endif
LinkerType linker_type = linker_find_linker_type();
linker_setup(&args, files_to_link, file_count, output_file, linker_type);
VECEACH(active_target.link_args, i)
{
vec_add(args, active_target.link_args[i]);
}
const char *error = NULL;
// This isn't used in most cases, but its contents should get freed after linking.
WindowsLinkPathsUTF8 windows_paths = { 0 };
switch (platform_target.os)
{
case OS_TYPE_WIN32:
// TODO: properly detect if llvm-lld is available
// TODO: check if running inside MSYS2, it could be done via getting MSYSTEM environment variable
// https://stackoverflow.com/questions/65527286/how-to-check-if-my-program-is-running-on-mingwor-msys-shell-or-on-cmd
if (NULL == getenv("MSYSTEM"))
{
// "native" windows
// find paths to library directories.
// ex:
// C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\lib\\x64
// C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\atlmfc\\lib\\x64
// C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.19041.0\\ucrt\\x64
// C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.19041.0\\um\\x64
#ifdef _MSC_VER
windows_paths = get_windows_link_paths();
vec_add(args, join_strings((const char* []) { "-libpath:", windows_paths.windows_sdk_um_library_path }, 2));
vec_add(args, join_strings((const char* []) { "-libpath:", windows_paths.windows_sdk_ucrt_library_path }, 2));
vec_add(args, join_strings((const char* []) { "-libpath:", windows_paths.vs_library_path }, 2));
vec_add(args, "-defaultlib:libcmt");
vec_add(args, "-nologo");
add_files(&args, files_to_link, file_count);
#else
error_exit("ERROR - c3c must be compiled with MSVC to target x64-windows\n");
#endif
}
else
{
if (!strcmp(getenv("MSYSTEM"), "CLANG64") || !strcmp(getenv("MSYSTEM"), "MINGW64"))
{
prepare_msys2_linker_flags(&args, files_to_link, file_count);
}
else
{
return false;
}
}
break;
case OS_TYPE_MACOSX:
add_files(&args, files_to_link, file_count);
vec_add(args, "-lSystem");
vec_add(args, "-lm");
vec_add(args, "-syslibroot");
vec_add(args, "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk");
append_linker_pie_options(platform_target.reloc_model, &args);
if (platform_target.reloc_model == RELOC_SMALL_PIE || platform_target.reloc_model == RELOC_BIG_PIE)
{
vec_add(args, "-macosx_version_min");
vec_add(args, platform_target.arch == ARCH_TYPE_AARCH64 ? "11.0" : "10.8");
}
break;
case OS_TYPE_WATCHOS:
case OS_TYPE_IOS:
return false;
case OS_TYPE_WASI:
return false;
case OS_TYPE_OPENBSD:
case OS_TYPE_NETBSD:
case OS_TYPE_FREE_BSD:
return false;
case OS_TYPE_LINUX:
vec_add(args, "-m");
switch (platform_target.arch)
{
case ARCH_TYPE_X86_64:
vec_add(args, "elf_x86_64");
append_linker_pie_options(platform_target.reloc_model, &args);
if (is_pie_pic(platform_target.reloc_model))
{
vec_add(args, "--eh-frame-hdr");
vec_add(args, "/usr/lib/x86_64-linux-gnu/crt1.o");
vec_add(args, "/usr/lib/gcc/x86_64-linux-gnu/10/crtbeginS.o");
add_files(&args, files_to_link, file_count);
vec_add(args, "/usr/lib/x86_64-linux-gnu/crti.o");
vec_add(args, "/usr/lib/gcc/x86_64-linux-gnu/10/crtendS.o");
}
else
{
vec_add(args, "/usr/lib/x86_64-linux-gnu/Scrt1.o");
vec_add(args, "/usr/lib/gcc/x86_64-linux-gnu/10/crtbegin.o");
add_files(&args, files_to_link, file_count);
vec_add(args, "-lc");
vec_add(args, "-lm");
vec_add(args, "/usr/lib/x86_64-linux-gnu/crti.o");
vec_add(args, "/usr/lib/gcc/x86_64-linux-gnu/10/crtend.o");
}
vec_add(args, "/usr/lib/x86_64-linux-gnu/crtn.o");
vec_add(args, "-L/usr/lib/x86_64-linux-gnu/");
vec_add(args, "--dynamic-linker=/lib64/ld-linux-x86-64.so.2");
break;
case ARCH_TYPE_X86:
// vec_add(args, "elf_i386");
return false;
case ARCH_TYPE_AARCH64:
vec_add(args, "aarch64elf");
return false;
case ARCH_TYPE_RISCV32:
vec_add(args, "elf32lriscv");
return false;
case ARCH_TYPE_RISCV64:
vec_add(args, "elf64lriscv");
return false;
default:
UNREACHABLE
}
vec_add(args, "-L/usr/lib/");
vec_add(args, "-L/lib/");
break;
default:
add_files(&args, files_to_link, file_count);
append_linker_pie_options(platform_target.reloc_model, &args);
return false;
}
bool success;
const char *arg_list = "";
VECEACH(args, i)
{
arg_list = str_cat(arg_list, " ");
arg_list = str_cat(arg_list, args[i]);
}
DEBUG_LOG("Linker arguments: %s to %d", arg_list, platform_target.object_format);
switch (platform_target.object_format)
{
case OBJ_FORMAT_COFF:
if (platform_target.x64.is_mingw64)
{
success = llvm_link_mingw(args, (int)vec_size(args), &error);
}
else
{
success = llvm_link_coff(args, (int)vec_size(args), &error);
}
// This is only defined if compiling with MSVC
#ifdef _MSC_VER
if (windows_paths.windows_sdk_um_library_path) {
free_windows_link_paths(&windows_paths);
}
#endif
success = llvm_link_coff(args, (int)vec_size(args), &error);
break;
case OBJ_FORMAT_ELF:
success = llvm_link_elf(args, (int)vec_size(args), &error);
@@ -294,6 +474,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign
{
error_exit("Failed to create an executable: %s", error);
}
DEBUG_LOG("Linking complete.");
return true;
}
@@ -338,19 +519,11 @@ const char *concat_string_parts(const char **args)
void platform_linker(const char *output_file, const char **files, unsigned file_count)
{
DEBUG_LOG("Using cc linker.");
const char **parts = NULL;
vec_add(parts, active_target.cc ? active_target.cc : "cc");
VECEACH(active_target.link_args, i)
{
vec_add(parts, active_target.link_args[i]);
}
append_fpie_pic_options(platform_target.reloc_model, &parts);
vec_add(parts, "-o");
vec_add(parts, output_file);
for (unsigned i = 0; i < file_count; i++)
{
vec_add(parts, files[i]);
}
linker_setup(&parts, files, file_count, output_file, LINKER_CC);
vec_add(parts, "-lm");
const char *output = concat_string_parts(parts);
if (system(output) != 0)

View File

@@ -472,9 +472,11 @@ static void gencontext_verify_ir(GenContext *context)
}
}
void gencontext_emit_object_file(GenContext *context)
{
char *err = "";
DEBUG_LOG("Target: %s", platform_target.target_triple);
LLVMSetTarget(context->module, platform_target.target_triple);
char *layout = LLVMCopyStringRepOfTargetData(context->target_data);
LLVMSetDataLayout(context->module, layout);
@@ -666,12 +668,33 @@ void llvm_codegen_setup()
intrinsics_setup = true;
}
void llvm_set_comdat(GenContext *c, LLVMValueRef global)
{
if (!platform_target.use_comdat) return;
LLVMComdatRef comdat = LLVMGetOrInsertComdat(c->module, LLVMGetValueName(global));
LLVMSetComdatSelectionKind(comdat, LLVMAnyComdatSelectionKind);
LLVMSetComdat(global, comdat);
}
void llvm_set_linkonce(GenContext *c, LLVMValueRef global)
{
LLVMSetLinkage(global, LLVMLinkOnceAnyLinkage);
LLVMSetVisibility(global, LLVMDefaultVisibility);
llvm_set_comdat(c, global);
}
void llvm_set_weak(GenContext *c, LLVMValueRef global)
{
LLVMSetLinkage(global, LLVMWeakAnyLinkage);
LLVMSetVisibility(global, LLVMDefaultVisibility);
llvm_set_comdat(c, global);
}
void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
{
if (decl->module != c->code_module)
{
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
LLVMSetVisibility(value, LLVMDefaultVisibility);
llvm_set_linkonce(c, value);
return;
}
Visibility visibility = decl->visibility;
@@ -680,8 +703,7 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
{
case VISIBLE_MODULE:
case VISIBLE_PUBLIC:
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
LLVMSetVisibility(value, LLVMDefaultVisibility);
llvm_set_linkonce(c, value);
break;
case VISIBLE_EXTERN:
case VISIBLE_LOCAL:
@@ -725,7 +747,10 @@ void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl)
decl->enums.values[i]->backend_ref = llvm_emit_array_gep_raw(c, enum_elements, elements_type, i, alignment, &store_align);
}
}
LLVMValueRef global_name = LLVMAddGlobal(c->module, llvm_get_type(c, type_char), decl->name ? decl->name : "anon");
scratch_buffer_clear();
scratch_buffer_append("introspect.");
scratch_buffer_append(decl->name ? decl->name : "anon");
LLVMValueRef global_name = LLVMAddGlobal(c->module, llvm_get_type(c, type_char), scratch_buffer_to_string());
LLVMSetGlobalConstant(global_name, 1);
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
decl->type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));

View File

@@ -18,6 +18,7 @@ static void llvm_emit_initialize_designated(GenContext *c, BEValue *ref, AlignSi
static inline void llvm_emit_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
static inline void llvm_emit_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef failable)
{
assert(ref->kind == BE_ADDRESS || ref->kind == BE_ADDRESS_FAILABLE);
@@ -3281,7 +3282,6 @@ void gencontext_emit_binary(GenContext *c, BEValue *be_value, Expr *expr, BEValu
llvm_value_set(be_value, val, expr->type);
}
static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Expr *expr)
{
@@ -3343,8 +3343,7 @@ void llvm_emit_derived_backend_type(GenContext *c, Type *type)
return;
PRIMITIVE:
LLVMSetLinkage(global_name, LLVMWeakAnyLinkage);
LLVMSetVisibility(global_name, LLVMDefaultVisibility);
llvm_set_weak(c, global_name);
}
void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type)
@@ -3855,12 +3854,8 @@ static LLVMValueRef llvm_emit_real(LLVMTypeRef type, Float f)
return LLVMConstRealOfString(type, f.f < 0 ? "-inf" : "inf");
}
scratch_buffer_clear();
#if LONG_DOUBLE
global_context.scratch_buffer_len = sprintf(global_context.scratch_buffer, "%La", f.f);
#else
global_context.scratch_buffer_len = (uint32_t)sprintf(global_context.scratch_buffer, "%a", f.f);
#endif
return LLVMConstRealOfStringAndSize(type, global_context.scratch_buffer, global_context.scratch_buffer_len);
scratch_buffer_printf("%a", f.f);
return LLVMConstRealOfStringAndSize(type, scratch_buffer.str, scratch_buffer.len);
}
static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr)

View File

@@ -457,11 +457,11 @@ void llvm_emit_function_body(GenContext *c, Decl *decl)
LLVMTypeRef ptr_to_slot_type = LLVMPointerType(slot_type, 0);
if (!c->debug.last_ptr)
{
LLVMValueRef last_stack = c->debug.last_ptr = LLVMAddGlobal(c->module, ptr_to_slot_type, ".$last_stack");
const char *name = ".$last_stack";
LLVMValueRef last_stack = c->debug.last_ptr = LLVMAddGlobal(c->module, ptr_to_slot_type, name);
LLVMSetThreadLocal(last_stack, true);
LLVMSetInitializer(last_stack, LLVMConstNull(ptr_to_slot_type));
LLVMSetVisibility(last_stack, LLVMDefaultVisibility);
LLVMSetLinkage(last_stack, LLVMWeakODRLinkage);
llvm_set_weak(c, last_stack);
}
AlignSize alignment = llvm_abi_alignment(c, slot_type);
c->debug.stack_slot = llvm_emit_alloca(c, slot_type, alignment, ".$stackslot");
@@ -651,7 +651,15 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
switch (visibility)
{
case VISIBLE_EXTERN:
LLVMSetLinkage(function, decl->func_decl.attr_weak ? LLVMExternalWeakLinkage : LLVMExternalLinkage);
if (decl->func_decl.attr_weak)
{
LLVMSetLinkage(function, LLVMExternalWeakLinkage);
llvm_set_comdat(c, function);
}
else
{
LLVMSetLinkage(function, LLVMExternalLinkage);
}
LLVMSetVisibility(function, LLVMDefaultVisibility);
if (prototype->call_abi == CALL_X86_STD && platform_target.os == OS_TYPE_WIN32)
{
@@ -660,8 +668,7 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
break;
case VISIBLE_PUBLIC:
case VISIBLE_MODULE:
if (decl->func_decl.attr_weak) LLVMSetLinkage(function, LLVMWeakAnyLinkage);
LLVMSetVisibility(function, LLVMDefaultVisibility);
if (decl->func_decl.attr_weak) llvm_set_weak(c, function);
break;
case VISIBLE_LOCAL:
LLVMSetLinkage(function, decl->func_decl.attr_weak ? LLVMLinkerPrivateWeakLinkage : LLVMInternalLinkage);

View File

@@ -263,6 +263,9 @@ void llvm_emit_coerce_store(GenContext *c, LLVMValueRef addr, AlignSize alignmen
void llvm_emit_function_body(GenContext *context, Decl *decl);
void llvm_emit_function_decl(GenContext *c, Decl *decl);
void llvm_emit_introspection_type_from_decl(GenContext *c, Decl *decl);
void llvm_set_weak(GenContext *c, LLVMValueRef global);
void llvm_set_linkonce(GenContext *c, LLVMValueRef global);
void llvm_set_comdat(GenContext *c, LLVMValueRef global);
LLVMValueRef llvm_emit_call_intrinsic(GenContext *c, unsigned intrinsic, LLVMTypeRef *types, unsigned type_count, LLVMValueRef *values, unsigned arg_count);
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);

View File

@@ -10,8 +10,8 @@ void gencontext_begin_module(GenContext *c)
assert(!c->module && "Expected no module");
const char *result = module_create_object_file_name(c->code_module);
c->ir_filename = strformat("%s.ll", result);
c->object_filename = strformat("%s%s", result, get_object_extension());
c->ir_filename = str_printf("%s.ll", result);
c->object_filename = str_printf("%s%s", result, get_object_extension());
c->panicfn = global_context.panic_fn;
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);

View File

@@ -1018,7 +1018,7 @@ static inline void llvm_emit_asm_stmt(GenContext *c, Ast *ast)
LLVMValueRef asm_fn = LLVMGetInlineAsm(asm_fn_type,
(char *)ast->asm_stmt.body->const_expr.string.chars,
ast->asm_stmt.body->const_expr.string.len,
scratch_buffer_to_string(), global_context.scratch_buffer_len,
scratch_buffer_to_string(), scratch_buffer.len,
ast->asm_stmt.is_volatile,
true,
LLVMInlineAsmDialectIntel

View File

@@ -0,0 +1,46 @@
#include "compiler_internal.h"
#include "utils/json.h"
const char *macos_sysroot(void)
{
#if __APPLE__
static const char *xcode_sysroot = "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk";
static const char *commandline_tool_sysroot = "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk";
if (file_is_dir(xcode_sysroot)) return xcode_sysroot;
if (file_is_dir(commandline_tool_sysroot)) return commandline_tool_sysroot;
#endif
return NULL;
}
void parse_version(const char *version_string, Version *version)
{
StringSlice slice = slice_from_string(version_string);
StringSlice first = slice_next_token(&slice, '.');
version->major = atoi(first.ptr);
version->minor = atoi(slice.ptr);
}
MacSDK *macos_sysroot_sdk_information(const char *sdk_path)
{
JsonParser parser;
size_t len;
scratch_buffer_clear();
scratch_buffer_printf("%s/SDKSettings.json", sdk_path);
const char *settings_json_path = scratch_buffer_to_string();
if (!file_exists(settings_json_path)) error_exit("Invalid MacOS SDK path: '%s'.", sdk_path);
const char *file = file_read_all(settings_json_path, &len);
json_init_string(&parser, file, &malloc_arena);
MacSDK *sdk = CALLOCS(MacSDK);
JSONObject *top_object = json_parse(&parser);
JSONObject *supported_targets = json_obj_get(top_object, "SupportedTargets");
JSONObject *macosx_target = json_obj_get(supported_targets, "macosx");
const char *default_deploy_target = json_obj_get(macosx_target, "DefaultDeploymentTarget")->str;
parse_version(default_deploy_target, &sdk->macos_deploy_target);
const char *min_deploy_target = json_obj_get(macosx_target, "MinimumDeploymentTarget")->str;
parse_version(min_deploy_target, &sdk->macos_min_deploy_target);
return sdk;
}

View File

@@ -12,10 +12,10 @@ Decl *module_find_symbol(Module *module, const char *symbol)
const char *module_create_object_file_name(Module *module)
{
scratch_buffer_clear();
StringSlice slice = strtoslice(module->name->module);
StringSlice slice = slice_from_string(module->name->module);
while (true)
{
StringSlice part = strnexttok(&slice, ':');
StringSlice part = slice_next_token(&slice, ':');
scratch_buffer_append_len(part.ptr, part.len);
if (!slice.len) break;
slice.ptr++;

View File

@@ -224,15 +224,9 @@ const char *expr_const_to_error_string(const ExprConst *expr)
case CONST_INTEGER:
return int_to_str(expr->ixx, 10);
case CONST_FLOAT:
#if LONG_DOUBLE
asprintf(&buff, "%Lg", expr->fxx.f);
#else
asprintf(&buff, "%g", expr->fxx.f);
#endif
return buff;
return str_printf("%g", expr->fxx.f);
case CONST_STRING:
asprintf(&buff, "\"%*.s\"", expr->string.len, expr->string.chars);
return buff;
return str_printf("\"%*.s\"", expr->string.len, expr->string.chars);
case CONST_BYTES:
return "<binary data>";
case CONST_ENUM:

View File

@@ -456,7 +456,7 @@ static Expr *parse_ct_stringify(ParseContext *c, Expr *left)
return expr;
}
size_t len = end - start;
const char *content = copy_string(start, len);
const char *content = str_copy(start, len);
Expr *expr = expr_new(EXPR_CONST, start_span);
expr->const_expr.const_kind = CONST_STRING;
expr->const_expr.string.chars = content;
@@ -1153,7 +1153,7 @@ static Expr *parse_integer(ParseContext *c, Expr *left)
if (ch == '_') continue;
if (i.high > max) wrapped = true;
i = i128_shl64(i, 4);
i = i128_add64(i, (uint64_t) hex_nibble(ch));
i = i128_add64(i, (uint64_t) char_hex_to_nibble(ch));
hex_characters++;
}
break;
@@ -1322,8 +1322,8 @@ static void parse_hex(char *result_pointer, const char *data, const char *end)
{
int val;
int val2;
while ((val = char_to_nibble(*(data++))) < 0) if (data == end) goto DONE;
while ((val2 = char_to_nibble(*(data++))) < 0);
while ((val = char_hex_to_nibble(*(data++))) < 0) if (data == end) goto DONE;
while ((val2 = char_hex_to_nibble(*(data++))) < 0);
*(data_current++) = (char)((val << 4) | val2);
}
@@ -1496,14 +1496,14 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
{
int scanned;
uint64_t unicode_char;
signed char scanned_char = is_valid_escape(src[0]);
signed char scanned_char = char_is_valid_escape(src[0]);
if (scanned_char < 0) return -1;
switch (scanned_char)
{
case 'x':
{
int h = char_to_nibble(src[1]);
int l = char_to_nibble(src[2]);
int h = char_hex_to_nibble(src[1]);
int l = char_hex_to_nibble(src[2]);
if (h < 0 || l < 0) return -1;
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
scanned = 3;
@@ -1511,10 +1511,10 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
}
case 'u':
{
int x1 = char_to_nibble(src[1]);
int x2 = char_to_nibble(src[2]);
int x3 = char_to_nibble(src[3]);
int x4 = char_to_nibble(src[4]);
int x1 = char_hex_to_nibble(src[1]);
int x2 = char_hex_to_nibble(src[2]);
int x3 = char_hex_to_nibble(src[3]);
int x4 = char_hex_to_nibble(src[4]);
if (x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0) return -1;
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
scanned = 5;
@@ -1522,14 +1522,14 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
}
case 'U':
{
int x1 = char_to_nibble(src[1]);
int x2 = char_to_nibble(src[2]);
int x3 = char_to_nibble(src[3]);
int x4 = char_to_nibble(src[4]);
int x5 = char_to_nibble(src[5]);
int x6 = char_to_nibble(src[6]);
int x7 = char_to_nibble(src[7]);
int x8 = char_to_nibble(src[8]);
int x1 = char_hex_to_nibble(src[1]);
int x2 = char_hex_to_nibble(src[2]);
int x3 = char_hex_to_nibble(src[3]);
int x4 = char_hex_to_nibble(src[4]);
int x5 = char_hex_to_nibble(src[5]);
int x6 = char_hex_to_nibble(src[6]);
int x7 = char_hex_to_nibble(src[7]);
int x8 = char_hex_to_nibble(src[8]);
if (x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0 || x5 < 0 || x6 < 0 || x7 < 0 || x8 < 0) return -1;
unicode_char = ((unsigned) x1 << 28U) + ((unsigned) x2 << 24U) + ((unsigned) x3 << 20U) + ((unsigned) x4 << 16U) +
((unsigned) x5 << 12U) + ((unsigned) x6 << 8U) + ((unsigned) x7 << 4U) + (unsigned)x8;

View File

@@ -243,7 +243,7 @@ static inline Path *parse_module_path(ParseContext *c)
}
scratch_buffer_append("::");
}
return path_create_from_string(scratch_buffer_to_string(), global_context.scratch_buffer_len, span);
return path_create_from_string(scratch_buffer_to_string(), scratch_buffer.len, span);
}
@@ -417,7 +417,7 @@ Path *parse_path_prefix(ParseContext *c, bool *had_error)
*had_error = false;
if (!tok_is(c, TOKEN_IDENT) || peek(c) != TOKEN_SCOPE) return NULL;
char *scratch_ptr = global_context.scratch_buffer;
char *scratch_ptr = scratch_buffer.str;
uint32_t offset = 0;
Path *path = CALLOCS(Path);

View File

@@ -661,11 +661,7 @@ bool may_convert_float_const_implicit(Expr *expr, Type *to_type)
{
if (!float_const_fits_type(&expr->const_expr, type_flatten(to_type)->type_kind))
{
#if LONG_DOUBLE
ERROR_NODE(expr, "The value '%Lg' is out of range for %s, so you need an explicit cast to truncate the value.", expr->const_expr.fxx.f, type_quoted_error_string(to_type));
#else
SEMA_ERROR(expr, "The value '%g' is out of range for %s, so you need an explicit cast to truncate the value.", expr->const_expr.fxx.f, type_quoted_error_string(to_type));
#endif
return false;
}
return true;

View File

@@ -17,23 +17,23 @@ static bool sema_check_section(SemaContext *context, Decl *decl, Attr *attr)
return true;
}
scratch_buffer_clear();
StringSlice slice = strtoslice(section_string);
StringSlice segment = strnexttok(&slice, ',');
StringSlice section = strnexttok(&slice, ',');
StringSlice attrs = strnexttok(&slice, ',');
StringSlice stub_size_str = strnexttok(&slice, ',');
StringSlice slice = slice_from_string(section_string);
StringSlice segment = slice_next_token(&slice, ',');
StringSlice section = slice_next_token(&slice, ',');
StringSlice attrs = slice_next_token(&slice, ',');
StringSlice stub_size_str = slice_next_token(&slice, ',');
if (slice.len)
{
SEMA_ERROR(attr->expr, "Too many parts to the Mach-o section description.");
}
slicetrim(&segment);
slice_trim(&segment);
if (segment.len == 0)
{
SEMA_ERROR(attr->expr, "The segment is missing, did you type it correctly?");
return false;
}
slicetrim(&section);
slice_trim(&section);
if (section.len == 0)
{
SEMA_ERROR(attr->expr, "Mach-o requires 'segment,section' as the format, did you type it correctly?");
@@ -2172,7 +2172,7 @@ static bool sema_analyse_parameterized_define(SemaContext *c, Decl *decl)
Path *path = CALLOCS(Path);
path->module = path_string;
path->span = module->name->span;
path->len = global_context.scratch_buffer_len;
path->len = scratch_buffer.len;
instantiated_module = module_instantiate_generic(module, path, decl->define_decl.generic_params);
sema_analyze_stage(instantiated_module, c->unit->module->stage);
}

View File

@@ -3083,11 +3083,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
{
expr->expr_kind = EXPR_CONST;
expr->const_expr.const_kind = CONST_FLOAT;
#if LONG_DOUBLE
expr->const_expr.fxx = (Float) { nanl(""), canonical->type_kind };
#else
expr->const_expr.fxx = (Float) { nan(""), canonical->type_kind };
#endif
expr->type = parent->type;
expr->resolve_status = RESOLVE_DONE;
return true;
@@ -7376,7 +7372,7 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char
for (ArraySize i = 0; i < len; i++)
{
char ch = string[i];
if (!is_alphanum_(ch))
if (!char_is_alphanum_(ch))
{
if (ch == ':' && i > 0 && string[i + 1] == ':')
{
@@ -7407,7 +7403,7 @@ bool splitpathref(const char *string, ArraySize len, Path **path_ref, const char
for (size_t i = 0; i < len; i++)
{
char c = string[i];
if (!is_alphanum_(c)) return false;
if (!char_is_alphanum_(c)) return false;
hash = FNV1a(c, hash);
}
*ident_ref = symtab_find(string, len, hash, type_ref);

View File

@@ -47,12 +47,12 @@ File *source_file_load(const char *filename, bool *already_loaded)
}
size_t size;
const char* source_text = read_file(filename, &size);
const char* source_text = file_read_all(filename, &size);
File *file = CALLOCS(File);
file->file_id = vec_size(global_context.loaded_sources);
file->full_path = full_path;
file->contents = source_text;
path_get_dir_and_filename_from_full(file->full_path, &file->name, &file->dir_path);
file_get_dir_and_filename_from_full(file->full_path, &file->name, &file->dir_path);
vec_add(global_context.loaded_sources, file);
return file;
}

View File

@@ -100,9 +100,9 @@ void symtab_init(uint32_t capacity)
{
const char* name = token_type_to_string((TokenType)i);
// Skip non-keywords
if (!is_lower(name[0]))
if (!char_is_lower(name[0]))
{
if ((name[0] != '@' && name[0] != '$') || !is_lower(name[1])) continue;
if ((name[0] != '@' && name[0] != '$') || !char_is_lower(name[1])) continue;
}
uint32_t len = (uint32_t)strlen(name);
TokenType type = (TokenType)i;
@@ -239,7 +239,7 @@ const char *symtab_add(const char *data, uint32_t len, uint32_t fnv1hash, TokenT
node->next = NULL;
node->index = fnv1hash;
node->type = *type;
return node->symbol = copy_string(data, len);
return node->symbol = str_copy(data, len);
}
SymtabEntry *bucket = first_bucket;
do
@@ -257,7 +257,7 @@ const char *symtab_add(const char *data, uint32_t len, uint32_t fnv1hash, TokenT
node->key_len = len;
node->index = fnv1hash;
node->type = *type;
return node->symbol = copy_string(data, len);
return node->symbol = str_copy(data, len);
}

View File

@@ -174,8 +174,7 @@ void llvm_dump(void)
}
LLVMTargetRef target;
char *error;
char *triplet = NULL;
asprintf(&triplet, "%s-unknown-%s-unknown", archs[i], os[j]);
char *triplet = str_printf("%s-unknown-%s-unknown", archs[i], os[j]);
if (LLVMGetTargetFromTriple(triplet, &target, &error)) continue;
LLVMTargetMachineRef machine = NULL;
if (!(machine = LLVMCreateTargetMachine(target, triplet, "", "", 0, LLVMRelocDefault, LLVMCodeModelDefault))) {
@@ -461,7 +460,9 @@ static inline void target_setup_x64_abi(BuildTarget *target)
if (target->feature.soft_float == SOFT_FLOAT_YES) platform_target.x64.soft_float = true;
if (platform_target.environment_type == ENV_TYPE_GNU)
{
platform_target.x64.is_mingw64 = platform_target.x64.is_win64;
//platform_target.x64.is_mingw64 = platform_target.x64.is_win64;
if (platform_target.x64.is_win64) DEBUG_LOG("Mingw");
}
if (platform_target.os == OS_TYPE_LINUX || platform_target.os == OS_TYPE_NETBSD)
{
@@ -484,29 +485,70 @@ static inline void target_setup_x64_abi(BuildTarget *target)
}
}
const char *arch_to_linker_arch(ArchType arch)
{
switch (arch)
{
case ARCH_UNSUPPORTED:
case ARCH_TYPE_UNKNOWN:
return "unknown";
case ARCH_TYPE_ARM:
return "arm";
case ARCH_TYPE_ARMB:
return "armeb";
case ARCH_TYPE_AARCH64:
return "aarch64";
case ARCH_TYPE_AARCH64_BE:
return "aarch64_be";
case ARCH_TYPE_PPC:
return "ppc";
case ARCH_TYPE_PPC64:
return "ppc64";
case ARCH_TYPE_PPC64LE:
return "ppc64le";
case ARCH_TYPE_RISCV32:
return "riscv32";
case ARCH_TYPE_RISCV64:
return "riscv64";
case ARCH_TYPE_THUMB:
return "thumb";
case ARCH_TYPE_THUMBEB:
return "thumbeb";
case ARCH_TYPE_X86:
return "i386";
case ARCH_TYPE_X86_64:
return "x86_64";
case ARCH_TYPE_WASM32:
return "wasm32";
case ARCH_TYPE_WASM64:
return "wasm64";
}
UNREACHABLE;
}
static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = {
[X86_FREEBSD] = "i386-unknown-freebsd",
[X86_OPENBSD] = "i386-unknown-openbsd",
[X86_NETBSD] = "i386-unknown-netbsd",
[X86_MCU] = "i386-pc-elfiamcu",
[X86_WINDOWS] = "i386-pc-win32",
[X86_LINUX] = "i386-unknown-linux",
[X86_ELF] = "i386-unknown-elf",
[X64_DARWIN] = "x86_64-apple-darwin-1",
[X64_LINUX] = "x86_64-pc-linux-gnu",
[X64_WINDOWS] = "x86_64-pc-windows-msvc",
[X64_WINDOWS_GNU] = "x86_64-w64-windows-gnu",
[X64_NETBSD] = "x86_64-pc-netbsd",
[X64_FREEBSD] = "x86_64-pc-freebsd",
[X64_OPENBSD] = "x86_64-pc-openbsd",
[X64_ELF] = "x86_64-unknown-elf",
[AARCH64_LINUX] = "aarch64-unknown-linux-gnu",
[AARCH64_DARWIN] = "aarch64-apple-darwin",
[AARCH64_ELF] = "aarch64-unknown-elf",
[RISCV32_LINUX] = "riscv32-unknown-linux",
[RISCV32_ELF] = "riscv32-unknown-elf",
[RISCV64_LINUX] = "riscv64-unknown-linux",
[RISCV64_ELF] = "riscv64-unknown-elf",
[FREEBSD_X86] = "i386-unknown-freebsd",
[OPENBSD_X86] = "i386-unknown-openbsd",
[NETBSD_X86] = "i386-unknown-netbsd",
[MCU_X86] = "i386-pc-elfiamcu",
[WINDOWS_X86] = "i386-pc-win32",
[LINUX_X86] = "i386-unknown-linux",
[ELF_X86] = "i386-unknown-elf",
[MACOS_X64] = "x86_64-apple-darwin",
[LINUX_X64] = "x86_64-pc-linux-gnu",
[WINDOWS_X64] = "x86_64-pc-windows-msvc",
[MINGW_X64] = "x86_64-w64-windows-gnu",
[NETBSD_X64] = "x86_64-pc-netbsd",
[FREEBSD_X64] = "x86_64-pc-freebsd",
[OPENBSD_X64] = "x86_64-pc-openbsd",
[ELF_X64] = "x86_64-unknown-elf",
[LINUX_AARCH64] = "aarch64-unknown-linux-gnu",
[MACOS_AARCH64] = "aarch64-apple-darwin",
[ELF_AARCH64] = "aarch64-unknown-elf",
[LINUX_RISCV32] = "riscv32-unknown-linux",
[ELF_RISCV32] = "riscv32-unknown-elf",
[LINUX_RISCV64] = "riscv64-unknown-linux",
[ELF_RISCV64] = "riscv64-unknown-elf",
[WASM32] = "wasm32-unknown-unknown",
[WASM64] = "wasm64-unknown-unknown",
};
@@ -530,9 +572,10 @@ static bool arch_is_supported(ArchType arch)
return false;
}
}
static ArchType arch_from_llvm_string(StringSlice slice)
{
#define STRCASE(_str, _arch) if (slicestrcmp(slice, _str)) return _arch;
#define STRCASE(_str, _arch) if (slice_strcmp(slice, _str)) return _arch;
STRCASE("i386", ARCH_TYPE_X86)
STRCASE("i486", ARCH_TYPE_X86)
STRCASE("i586", ARCH_TYPE_X86)
@@ -635,28 +678,28 @@ static EnvironmentType environment_type_from_llvm_string(StringSlice env)
}
}
#define STRCASE(_str, _arch) if (slicestrcmp(env, _str)) return _arch;
STRCASE("gnu", ENV_TYPE_GNU)
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
STRCASE("gnueabihf", ENV_TYPE_GNUEABIHF)
STRCASE("gnueabi", ENV_TYPE_GNUEABI)
STRCASE("gnux32", ENV_TYPE_GNUX32)
STRCASE("code16", ENV_TYPE_CODE16)
STRCASE("eabi", ENV_TYPE_EABI)
STRCASE("eabihf", ENV_TYPE_EABIHF)
STRCASE("elfv1", ENV_TYPE_ELFV1)
STRCASE("elfv2", ENV_TYPE_ELFV2)
STRCASE("android", ENV_TYPE_ANDROID)
STRCASE("musl", ENV_TYPE_MUSL)
STRCASE("musleabi", ENV_TYPE_MUSLEABI)
STRCASE("musleabihf", ENV_TYPE_MUSLEABIHF)
STRCASE("msvc", ENV_TYPE_MSVC)
STRCASE("itanium", ENV_TYPE_ITANIUM)
STRCASE("cygnus", ENV_TYPE_CYGNUS)
STRCASE("coreclr", ENV_TYPE_CORECLR)
STRCASE("simulator", ENV_TYPE_SIMULATOR)
STRCASE("macabi", ENV_TYPE_MACABI)
#define STRCASE(_str, _arch) if (slice_strcmp(env, _str)) return _arch;
STRCASE("gnu", ENV_TYPE_GNU)
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
STRCASE("gnueabihf", ENV_TYPE_GNUEABIHF)
STRCASE("gnueabi", ENV_TYPE_GNUEABI)
STRCASE("gnux32", ENV_TYPE_GNUX32)
STRCASE("code16", ENV_TYPE_CODE16)
STRCASE("eabi", ENV_TYPE_EABI)
STRCASE("eabihf", ENV_TYPE_EABIHF)
STRCASE("elfv1", ENV_TYPE_ELFV1)
STRCASE("elfv2", ENV_TYPE_ELFV2)
STRCASE("android", ENV_TYPE_ANDROID)
STRCASE("musl", ENV_TYPE_MUSL)
STRCASE("musleabi", ENV_TYPE_MUSLEABI)
STRCASE("musleabihf", ENV_TYPE_MUSLEABIHF)
STRCASE("msvc", ENV_TYPE_MSVC)
STRCASE("itanium", ENV_TYPE_ITANIUM)
STRCASE("cygnus", ENV_TYPE_CYGNUS)
STRCASE("coreclr", ENV_TYPE_CORECLR)
STRCASE("simulator", ENV_TYPE_SIMULATOR)
STRCASE("macabi", ENV_TYPE_MACABI)
return ENV_TYPE_UNKNOWN;
#undef STRCASE
}
@@ -672,7 +715,7 @@ static OsType os_from_llvm_string(StringSlice os_string)
break;
}
}
#define STRCASE(_str, _os) if (slicestrcmp(os_string, _str)) return _os;
#define STRCASE(_str, _os) if (slice_strcmp(os_string, _str)) return _os;
STRCASE("ananas", OS_TYPE_ANANAS)
STRCASE("cloudabi", OS_TYPE_CLOUD_ABI)
STRCASE("darwin", OS_TYPE_MACOSX)
@@ -715,7 +758,7 @@ static OsType os_from_llvm_string(StringSlice os_string)
static VendorType vendor_from_llvm_string(StringSlice slice)
{
#define STRCASE(_str, _vendor) if (slicestrcmp(slice, _str)) return _vendor;
#define STRCASE(_str, _vendor) if (slice_strcmp(slice, _str)) return _vendor;
STRCASE("apple", VENDOR_APPLE)
STRCASE("pc", VENDOR_PC)
STRCASE("scei", VENDOR_SCEI)
@@ -1256,14 +1299,7 @@ void target_setup(BuildTarget *target)
if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT) target->arch_os_target = default_target;
if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT)
{
platform_target.target_triple = LLVM_DEFAULT_TARGET_TRIPLE;
}
else
{
platform_target.target_triple = arch_to_target_triple[target->arch_os_target];
}
platform_target.target_triple = arch_to_target_triple[target->arch_os_target];
platform_target.alloca_address_space = 0;
@@ -1299,18 +1335,18 @@ void target_setup(BuildTarget *target)
LLVMTargetMachineRef machine = llvm_target_machine_create();
char *target_triple = LLVMGetTargetMachineTriple(machine);
platform_target.target_triple = copy_string(target_triple, strlen(target_triple));
platform_target.target_triple = str_copy(target_triple, strlen(target_triple));
LLVMDisposeMessage(target_triple);
LLVMDisposeTargetMachine(machine);
StringSlice target_triple_string = strtoslice(platform_target.target_triple);
platform_target.arch = arch_from_llvm_string(strnexttok(&target_triple_string, '-'));
StringSlice target_triple_string = slice_from_string(platform_target.target_triple);
platform_target.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-'));
if (!arch_is_supported(platform_target.arch))
{
printf("WARNING! This architecture is not supported.\n");
}
platform_target.vendor = vendor_from_llvm_string(strnexttok(&target_triple_string, '-'));
platform_target.os = os_from_llvm_string(strnexttok(&target_triple_string, '-'));
platform_target.vendor = vendor_from_llvm_string(slice_next_token(&target_triple_string, '-'));
platform_target.os = os_from_llvm_string(slice_next_token(&target_triple_string, '-'));
platform_target.environment_type = environment_type_from_llvm_string(target_triple_string);
platform_target.float_abi = false;
@@ -1322,6 +1358,17 @@ void target_setup(BuildTarget *target)
platform_target.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch);
platform_target.alloca_address_space = 0;
platform_target.object_format = object_format_from_os(platform_target.os);
switch (platform_target.object_format)
{
case OBJ_FORMAT_COFF:
case OBJ_FORMAT_ELF:
case OBJ_FORMAT_WASM:
platform_target.use_comdat = true;
break;
default:
break;
}
platform_target.int128 = os_target_supports_int128(platform_target.os, platform_target.arch);
platform_target.vec128f = os_target_supports_vec(platform_target.os, platform_target.arch, 128, false);
@@ -1422,7 +1469,6 @@ void target_setup(BuildTarget *target)
platform_target.environment_type,
active_target.type != TARGET_TYPE_EXECUTABLE);
platform_target.pic_required = arch_os_pic_default_forced(platform_target.arch, platform_target.os);
// Override PIC, but only if the platform does not require PIC
if (target->reloc_model != RELOC_DEFAULT
&& (target->reloc_model != RELOC_NONE || !platform_target.pic_required))

View File

@@ -266,6 +266,7 @@ typedef struct
bool signed_c_char : 1;
FloatABI float_abi : 3;
unsigned default_number_regs_x86 : 8;
bool use_comdat : 1;
union
{
struct

View File

@@ -91,14 +91,11 @@ Type *type_int_unsigned_by_bitsize(unsigned bytesize)
const char *type_quoted_error_string(Type *type)
{
char *buffer = NULL;
if (type->canonical != type)
{
asprintf(&buffer, "'%s' (%s)", type_to_error_string(type), type_to_error_string(type->canonical));
return buffer;
return str_printf("'%s' (%s)", type_to_error_string(type), type_to_error_string(type->canonical));
}
asprintf(&buffer, "'%s'", type_to_error_string(type));
return buffer;
return str_printf("'%s'", type_to_error_string(type));
}
static void type_append_func_to_scratch(FunctionPrototype *prototype);
@@ -208,7 +205,6 @@ static void type_append_func_to_scratch(FunctionPrototype *prototype)
const char *type_to_error_string(Type *type)
{
char *buffer = NULL;
switch (type->type_kind)
{
case TYPE_POISONED:
@@ -231,11 +227,9 @@ const char *type_to_error_string(Type *type)
case TYPE_FUNC:
scratch_buffer_clear();
type_append_func_to_scratch(type->func.prototype);
asprintf(&buffer, "fn %s", scratch_buffer_to_string());
return buffer;
return str_printf("fn %s", scratch_buffer_to_string());
case TYPE_VECTOR:
asprintf(&buffer, "%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
return buffer;
return str_printf("%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_TYPEINFO:
return "typeinfo";
case TYPE_TYPEID:
@@ -247,22 +241,17 @@ const char *type_to_error_string(Type *type)
{
return type_to_error_string(type->pointer);
}
asprintf(&buffer, "%s*", type_to_error_string(type->pointer));
return buffer;
return str_printf("%s*", type_to_error_string(type->pointer));
case TYPE_FAILABLE:
if (!type->failable) return "void!";
asprintf(&buffer, "%s!", type_to_error_string(type->failable));
return buffer;
return str_printf("%s!", type_to_error_string(type->failable));
case TYPE_ARRAY:
asprintf(&buffer, "%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
return buffer;
return str_printf("%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
case TYPE_INFERRED_ARRAY:
case TYPE_FLEXIBLE_ARRAY:
asprintf(&buffer, "%s[*]", type_to_error_string(type->array.base));
return buffer;
return str_printf("%s[*]", type_to_error_string(type->array.base));
case TYPE_SUBARRAY:
asprintf(&buffer, "%s[]", type_to_error_string(type->array.base));
return buffer;
return str_printf("%s[]", type_to_error_string(type->array.base));
}
UNREACHABLE
}
@@ -555,7 +544,7 @@ static Type *type_generate_ptr(Type *ptr_type, bool canonical)
Type *ptr = ptr_type->type_cache[PTR_OFFSET];
if (ptr == NULL)
{
ptr = type_new(TYPE_POINTER, strformat("%s*", ptr_type->name));
ptr = type_new(TYPE_POINTER, str_printf("%s*", ptr_type->name));
ptr->pointer = ptr_type;
ptr_type->type_cache[PTR_OFFSET] = ptr;
if (ptr_type == ptr_type->canonical)
@@ -580,7 +569,7 @@ static Type *type_generate_failable(Type *failable_type, bool canonical)
Type *failable = failable_type->type_cache[FAILABLE_OFFSET];
if (failable == NULL)
{
failable = type_new(TYPE_FAILABLE, strformat("%s!", failable_type->name));
failable = type_new(TYPE_FAILABLE, str_printf("%s!", failable_type->name));
failable->pointer = failable_type;
failable_type->type_cache[FAILABLE_OFFSET] = failable;
if (failable_type == failable_type->canonical)
@@ -606,7 +595,7 @@ static Type *type_generate_subarray(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[SUB_ARRAY_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_SUBARRAY, strformat("%s[]", arr_type->name));
arr = type_new(TYPE_SUBARRAY, str_printf("%s[]", arr_type->name));
arr->array.base = arr_type;
arr_type->type_cache[SUB_ARRAY_OFFSET] = arr;
if (arr_type == arr_type->canonical)
@@ -632,7 +621,7 @@ static Type *type_generate_inferred_array(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[INFERRED_ARRAY_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_INFERRED_ARRAY, strformat("%s[*]", arr_type->name));
arr = type_new(TYPE_INFERRED_ARRAY, str_printf("%s[*]", arr_type->name));
arr->array.base = arr_type;
arr_type->type_cache[INFERRED_ARRAY_OFFSET] = arr;
if (arr_type == arr_type->canonical)
@@ -658,7 +647,7 @@ static Type *type_generate_flexible_array(Type *arr_type, bool canonical)
Type *arr = arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET];
if (arr == NULL)
{
arr = type_new(TYPE_FLEXIBLE_ARRAY, strformat("%s[*]", arr_type->name));
arr = type_new(TYPE_FLEXIBLE_ARRAY, str_printf("%s[*]", arr_type->name));
arr->array.base = arr_type;
arr->array.len = 0;
arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET] = arr;
@@ -869,13 +858,13 @@ static Type *type_create_array(Type *element_type, ArraySize len, bool vector, b
Type *vec_arr;
if (vector)
{
vec_arr = type_new(TYPE_VECTOR, strformat("%s[<%u>]", element_type->name, len));
vec_arr = type_new(TYPE_VECTOR, str_printf("%s[<%u>]", element_type->name, len));
vec_arr->array.base = element_type;
vec_arr->array.len = len;
}
else
{
vec_arr = type_new(TYPE_ARRAY, strformat("%s[%u]", element_type->name, len));
vec_arr = type_new(TYPE_ARRAY, str_printf("%s[%u]", element_type->name, len));
vec_arr->array.base = element_type;
vec_arr->array.len = len;
}

View File

@@ -0,0 +1,40 @@
// Copyright (c) 2022 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by a LGPLv3.0
// a copy of which can be found in the LICENSE file.
#include "compiler_internal.h"
static WindowsSDK *sdk = NULL;
// find paths to library directories.
// ex:
// C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\lib\\x64
// C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.28.29910\\atlmfc\\lib\\x64
// C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.19041.0\\ucrt\\x64
// C:\\Program Files (x86)\\Windows Kits\\10\\Lib\\10.0.19041.0\\um\\x64
#if PLATFORM_WINDOWS
WindowsSDK get_windows_link_paths(void);
void free_windows_link_paths(WindowsSDK* obj);
static WindowsSDK loaded;
WindowsSDK *windows_get_sdk(void)
{
if (!sdk)
{
loaded = get_windows_link_paths();
sdk = &loaded;
}
return sdk;
}
#else
WindowsSDK *windows_get_sdk(void)
{
return NULL;
}
#endif

View File

@@ -20,9 +20,7 @@
#define MAX_IDENTIFIER_LENGTH 31
#define MAX_SOURCE_LOCATION_LEN 255
#define PROJECT_JSON "project.c3p"
#ifndef __unused
#define __unused
#endif
#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( _WIN64 )
#define PLATFORM_WINDOWS 1
@@ -50,4 +48,13 @@
#undef IS_GCC
#define IS_GCC 1
#endif
#endif
#endif
#ifndef __printflike
#define __printflike(x, y)
#endif
#ifndef __unused
#define __unused
#endif

View File

@@ -48,7 +48,7 @@
#define TODO FATAL_ERROR("TODO reached");
#define TEST_ASSERT(condition_, string_) while (!(condition_)) { FATAL_ERROR(string_); }
#define TEST_ASSERTF(condition_, string_, ...) while (!(condition_)) { char* str_; asprintf(&str_, string_, __VA_ARGS__); FATAL_ERROR(str_); }
#define TEST_ASSERTF(condition_, string_, ...) while (!(condition_)) { char* str_ = str_printf(string_, __VA_ARGS__); FATAL_ERROR(str_); }
#define EXPECT(_string, _value, _expected) \
do { long long __tempval1 = _value; long long __tempval2 = _expected; \

View File

@@ -90,7 +90,7 @@ static inline bool is_path_separator(char c)
* @param directory_ptr the pointer to return the directory in.
* @return false if only a directory could be found, true otherwise
*/
bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr)
bool file_namesplit(const char *path, char** filename_ptr, char** directory_ptr)
{
size_t len = strlen(path);
if (len == 0) return false;
@@ -107,12 +107,12 @@ bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr)
if (file_len == 1 && path[0] == '.') return false;
if (file_len == 2 && path[0] == '.' && path[1] == '.') return false;
if (!file_len) return false;
*filename_ptr = copy_string(&path[len - file_len], file_len);
*filename_ptr = str_copy(&path[len - file_len], file_len);
if (!directory_ptr) return true;
if (file_len < len)
{
size_t dir_len = len - file_len;
*directory_ptr = copy_string(path, dir_len - 1);
*directory_ptr = str_copy(path, dir_len - 1);
}
else
{
@@ -124,21 +124,19 @@ bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr)
const char *expand_path(const char *path)
const char *file_expand_path(const char *path)
{
if (path[0] == '~' && path[1] == '/')
{
// Ignore leak.
char *ret = NULL;
char *home = getenv("HOME");
if (!home || asprintf(&ret, "%s%s", home, &path[1]) == -1) return &path[2];
return ret;
if (!home) return &path[2];
return str_printf("%s%s", home, &path[1]);
}
return path;
}
char *read_file(const char *path, size_t *return_size)
char *file_read_all(const char *path, size_t *return_size)
{
FILE *file = fopen(path, "rb");
@@ -190,21 +188,20 @@ char *read_file(const char *path, size_t *return_size)
static inline const char *lib_find(const char *exe_path, const char *rel_path)
{
struct stat info;
char *lib_path = NULL;
asprintf(&lib_path, "%s%sstd", exe_path, rel_path);
DEBUG_LOG("Checking %s", lib_path);
int err = stat(lib_path, &info);
scratch_buffer_clear();
scratch_buffer_printf("%s%sstd", exe_path, rel_path);
DEBUG_LOG("Checking %s", scratch_buffer_to_string());
int err = stat(scratch_buffer_to_string(), &info);
// Not a dir or had error?
if (err || !S_ISDIR(info.st_mode)) return NULL;
char *check_path = NULL;
asprintf(&check_path, "%s/libc.c3", lib_path);
DEBUG_LOG("Potential lib found, sanity check for libc...");
err = stat(check_path, &info);
scratch_buffer_append("/libc.c3");
err = stat(scratch_buffer_to_string(), &info);
if (err || !S_ISREG(info.st_mode)) return NULL;
asprintf(&lib_path, "%s%s", exe_path, rel_path);
const char *lib_path = str_printf("%s%s", exe_path, rel_path);
DEBUG_LOG("Library path found at %s", lib_path);
return lib_path;
}
@@ -233,9 +230,9 @@ const char *find_lib_dir(void)
return NULL;
}
void path_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path)
void file_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path)
{
if (!filenamesplit(full_path, filename, dir_path))
if (!file_namesplit(full_path, filename, dir_path))
{
error_exit("The filename could not be extracted from '%s'.", full_path);
}
@@ -285,6 +282,48 @@ bool file_has_suffix_in_list(const char *file_name, int name_len, const char **s
return false;
}
bool file_is_dir(const char *file)
{
struct stat st;
if (stat(file, &st)) return false;
return S_ISDIR(st.st_mode);
}
bool file_exists(const char *path)
{
struct stat st;
if (stat(path, &st)) return false;
return S_ISDIR(st.st_mode) || S_ISREG(st.st_mode) || S_ISREG(st.st_mode);
}
const char *file_append_path(const char *path, const char *name)
{
size_t path_len = strlen(path);
if (!path_len) return name;
if (path[path_len - 1] == '/') return str_cat(path, name);
return str_printf("%s/%s", path, name);
}
const char *file_first(const char *path)
{
#ifdef _MSC_VER
DIR *dir = opendir(strip_drive_prefix(path));
#else
DIR *dir = opendir(path);
#endif
if (!dir) return NULL;
struct dirent *ent;
while ((ent = readdir(dir)))
{
size_t name_len = strlen(ent->d_name);
if (name_len > 2)
{
return str_printf("%.*s", (int)name_len, ent->d_name);
}
}
return NULL;
}
void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char **suffix_list, int suffix_count)
{
#ifdef _MSC_VER
@@ -305,12 +344,8 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi
if (namelen < 3 || !file_has_suffix_in_list(ent->d_name, namelen, suffix_list, suffix_count))
{
char *new_path = NULL;
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
if (asprintf(&new_path, format, path, ent->d_name) == -1)
{
error_exit("Failed to allocate path.");
}
char *new_path = str_printf(format, path, ent->d_name);
bool is_directory;
struct stat st;
if (stat(new_path, &st))
@@ -323,15 +358,51 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi
{
file_add_wildcard_files(files, new_path, recursive, suffix_list, suffix_count);
}
free(new_path);
continue;
}
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
vec_add(*files, strformat(format, path, ent->d_name));
vec_add(*files, str_printf(format, path, ent->d_name));
}
closedir(dir);
}
#define BUFSIZE 1024
const char *execute_cmd(const char *cmd)
{
char buffer[BUFSIZE];
char *output = "";
FILE *process = NULL;
if (!(process = popen(cmd, "r")))
{
error_exit("Failed to open a pipe for command '%s'.", cmd);
}
while (fgets(buffer, BUFSIZE - 1, process))
{
output = str_cat(output, buffer);
}
if (pclose(process))
{
error_exit("Failed to execute '%s'.", cmd);
}
while (output[0] != 0)
{
switch (output[0])
{
case ' ':
case '\t':
case '\n':
case '\r':
output++;
continue;
default:
break;
}
break;
}
return str_trim(output);
}
#if PLATFORM_WINDOWS
char *realpath(const char *path, char *const resolved_path)

View File

@@ -1,6 +1,6 @@
#ifdef _MSC_VER
#include "lib.h"
#include "find_msvc.h"
#if PLATFORM_WINDOWS
#include <windows.h>
#include <string.h>
@@ -25,10 +25,10 @@ typedef struct
Find_Result find_visual_studio_and_windows_sdk();
void free_resources(Find_Result* result);
WindowsLinkPathsUTF8 get_windows_link_paths() {
WindowsSDK get_windows_link_paths() {
Find_Result paths = find_visual_studio_and_windows_sdk();
WindowsLinkPathsUTF8 out = { 0 };
WindowsSDK out = { 0 };
// note: WideCharToMultiByte doesn't seem to do null termination.
// I'm wary of manually adding a null terminator, so hopefully this is reliable.
@@ -75,7 +75,7 @@ WindowsLinkPathsUTF8 get_windows_link_paths() {
return out;
}
void free_windows_link_paths(WindowsLinkPathsUTF8* obj) {
void free_windows_link_paths(WindowsSDK* obj) {
free(obj->vs_library_path);
free(obj->windows_sdk_ucrt_library_path);
free(obj->windows_sdk_um_library_path);
@@ -95,6 +95,22 @@ void free_resources(Find_Result* result) {
free(result->vs_library_path);
}
#ifndef _Out_
#define _Out_
#endif
#ifndef _In_
#define _In_
#endif
#ifndef _Out_writes_to_
#define _Out_writes_to_(a, b)
#endif
#ifndef _Deref_out_opt_
#define _Deref_out_opt_
#endif
#ifndef _In_z_
#define _In_z_
#endif
#undef INTERFACE
#define INTERFACE ISetupInstance
DECLARE_INTERFACE_(ISetupInstance, IUnknown)
@@ -169,7 +185,7 @@ typedef struct {
bool os_file_exists(wchar_t* name) {
// @Robustness: What flags do we really want to check here?
auto attrib = GetFileAttributesW(name);
DWORD attrib = GetFileAttributesW(name);
if (attrib == INVALID_FILE_ATTRIBUTES) return false;
if (attrib & FILE_ATTRIBUTE_DIRECTORY) return false;
@@ -184,13 +200,13 @@ wchar_t* concat(wchar_t* a, wchar_t* b, wchar_t* c, wchar_t* d) {
// If you don't like that, use a programming language that actually
// helps you with using custom allocators. Or just edit the code.
auto len_a = wcslen(a);
auto len_b = wcslen(b);
size_t len_a = wcslen(a);
size_t len_b = wcslen(b);
auto len_c = 0;
size_t len_c = 0;
if (c) len_c = wcslen(c);
auto len_d = 0;
size_t len_d = 0;
if (d) len_d = wcslen(d);
wchar_t* result = (wchar_t*)malloc((len_a + len_b + len_c + len_d + 1) * 2);
@@ -242,7 +258,7 @@ wchar_t* find_windows_kit_root_with_key(HKEY key, wchar_t* version) {
// If that's not the right terminology, hey, I never do registry stuff.
DWORD required_length;
auto rc = RegQueryValueExW(key, version, NULL, NULL, NULL, &required_length);
LSTATUS rc = RegQueryValueExW(key, version, NULL, NULL, NULL, &required_length);
if (rc != 0) return NULL;
DWORD length = required_length + 2; // The +2 is for the maybe optional zero later on. Probably we are over-allocating.
@@ -264,7 +280,7 @@ void win10_best(wchar_t* short_name, wchar_t* full_name, Version_Data* data) {
// Find the Windows 10 subdirectory with the highest version number.
int i0, i1, i2, i3;
auto success = swscanf_s(short_name, L"%d.%d.%d.%d", &i0, &i1, &i2, &i3);
int success = swscanf_s(short_name, L"%d.%d.%d.%d", &i0, &i1, &i2, &i3);
if (success < 4) return;
if (i0 < data->best_version[0]) return;
@@ -295,7 +311,7 @@ void win8_best(wchar_t* short_name, wchar_t* full_name, Version_Data* data) {
// Find the Windows 8 subdirectory with the highest version number.
int i0, i1;
auto success = swscanf_s(short_name, L"winv%d.%d", &i0, &i1);
int success = swscanf_s(short_name, L"winv%d.%d", &i0, &i1);
if (success < 2) return;
if (i0 < data->best_version[0]) return;

View File

@@ -1,10 +0,0 @@
#pragma once
typedef struct {
char* windows_sdk_um_library_path;
char* windows_sdk_ucrt_library_path;
char* vs_library_path;
} WindowsLinkPathsUTF8;
WindowsLinkPathsUTF8 get_windows_link_paths();
void free_windows_link_paths(WindowsLinkPathsUTF8* obj);

View File

@@ -165,12 +165,12 @@ static void json_parse_string(JsonParser *parser)
char u2 = parser->current++[0];
char u3 = parser->current++[0];
char u4 = parser->current++[0];
if (!is_hex(u1) || !is_hex(u2) || !is_hex(u3) || !is_hex(u4))
if (!char_is_hex(u1) || !char_is_hex(u2) || !char_is_hex(u3) || !char_is_hex(u4))
{
json_error(parser, "Invalid hex in \\u escape sequence.");
return;
}
c = (hex_nibble(u1) << 12) + (hex_nibble(u2) << 8) + (hex_nibble(u3) << 4) + hex_nibble(u4);
c = (char_hex_to_nibble(u1) << 12) + (char_hex_to_nibble(u2) << 8) + (char_hex_to_nibble(u3) << 4) + char_hex_to_nibble(u4);
break;
}
default:

View File

@@ -64,4 +64,4 @@ typedef struct
void json_init_string(JsonParser *parser, const char *str, JsonAllocator *allocator);
JSONObject *json_parse(JsonParser *parser);
JSONObject *json_obj_get(JSONObject *obj, const char *key);
JSONObject *json_obj_get(JSONObject *obj, const char *key);

View File

@@ -11,14 +11,42 @@
#include "direct.h"
#endif
typedef struct StringSlice_
{
const char *ptr;
size_t len;
} StringSlice;
typedef struct
{
int major;
int minor;
} Version;
typedef struct
{
Version macos_deploy_target;
Version macos_min_deploy_target;
} MacSDK;
typedef struct {
char* windows_sdk_um_library_path;
char* windows_sdk_ucrt_library_path;
char* vs_library_path;
} WindowsSDK;
#define MAX_STRING_BUFFER 0x10000
#define COMPILER_SUCCESS_EXIT -1000
NORETURN void exit_compiler(int exit_value);
extern jmp_buf on_err_jump;
extern bool debug_log;
extern bool debug_stats;
extern uintptr_t arena_zero;
struct ScratchBuf { char str[MAX_STRING_BUFFER]; uint32_t len; };
extern struct ScratchBuf scratch_buffer;
NORETURN void exit_compiler(int exit_value);
typedef struct Task_
{
@@ -28,15 +56,20 @@ typedef struct Task_
typedef void *TaskQueueRef;
const char *str_without_suffix(const char *name, const char *suffix);
bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr);
const char* expand_path(const char* path);
bool file_namesplit(const char *path, char** filename_ptr, char** directory_ptr);
const char* file_expand_path(const char* path);
const char* find_lib_dir(void);
char *read_file(const char *path, size_t *return_size);
void path_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path);
bool file_is_dir(const char *file);
bool file_exists(const char *path);
char *file_read_all(const char *path, size_t *return_size);
void file_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path);
void file_find_top_dir();
bool file_has_suffix_in_list(const char *file_name, int name_len, const char **suffix_list, int suffix_count);
void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char **suffix_list, int suffix_count);
const char *file_first(const char *path);
const char *file_append_path(const char *path, const char *name);
const char *execute_cmd(const char *cmd);
void *cmalloc(size_t size);
void *ccalloc(size_t size, size_t elements);
void memory_init(void);
@@ -46,7 +79,6 @@ void memory_release();
#define idptr(id_) ((void*)(((uintptr_t)id_) * 16 + arena_zero))
void *calloc_arena(size_t mem);
char *calloc_string(size_t len);
char *copy_string(const char *start, size_t str_len);
#define malloc_string calloc_string
#define malloc_arena calloc_arena
void free_arena(void);
@@ -57,6 +89,78 @@ void taskqueue_add(TaskQueueRef queue, Task *task);
void taskqueue_destroy(TaskQueueRef queue);
void taskqueue_wait_for_completion(TaskQueueRef queue);
const char *str_remove_suffix(const char *name, const char *suffix);
char *str_trim(char *str);
const char *str_trim_start(const char *str);
void str_trim_end(char *str);
char *str_cat(const char *a, const char *b);
// Search a list of strings and return the matching element or -1 if none found.
int str_findlist(const char *value, unsigned count, const char** elements);
// Sprintf style, saved to an arena allocated string
char *str_printf(const char *var, ...) __printflike(1, 2);
char *str_vprintf(const char *var, va_list list);
void str_ellide_in_place(char *string, size_t max_size_shown);
bool str_is_valid_lowercase_name(const char *string);
bool str_has_no_uppercase(const char *string);
char *str_copy(const char *start, size_t str_len);
StringSlice slice_next_token(StringSlice *slice, char separator);
static inline bool slice_strcmp(StringSlice slice, const char *other);
static inline StringSlice slice_from_string(const char *data);
void slice_trim(StringSlice *slice);
void scratch_buffer_clear(void);
void scratch_buffer_append(const char *string);
void scratch_buffer_append_len(const char *string, size_t len);
void scratch_buffer_append_char(char c);
void scratch_buffer_append_signed_int(int64_t i);
UNUSED void scratch_buffer_append_unsigned_int(uint64_t i);
void scratch_buffer_printf(const char *format, ...);
char *scratch_buffer_to_string(void);
char *scratch_buffer_copy(void);
static inline bool is_power_of_two(uint64_t x);
static inline uint32_t next_highest_power_of_2(uint32_t v);
static inline bool char_is_lower(char c);
static inline bool char_is_lower_(char c);
static inline bool char_is_upper(char c);
static inline bool char_is_oct(char c);
static inline bool char_is_oct_or_(char c);
static inline bool char_is_binary(char c);
static inline bool char_is_binary_or_(char c);
static inline bool char_is_digit_or_(char c);
static inline bool char_is_digit(char c);
static inline bool char_is_hex(char c);
static inline bool char_is_hex_or_(char c);
static inline bool char_is_base64(char c);
static inline bool char_is_letter(char c);
static inline bool char_is_letter_(char c);
static inline bool char_is_alphanum_(char c);
static inline bool char_is_lower_alphanum_(char c);
static inline bool char_is_whitespace(char c);
static inline signed char char_is_valid_escape(char c);
// Hex to nibble, -1 if invalid
static inline int char_hex_to_nibble(char c);
static inline char char_nibble_to_hex(int c);
static inline uint32_t fnv1a(const char *key, uint32_t len);
static inline uint32_t vec_size(const void *vec);
static inline void vec_resize(void *vec, uint32_t new_size);
static inline void vec_pop(void *vec);
#define NUMBER_CHAR_CASE '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
#define UPPER_CHAR_CASE 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': \
case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': \
case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z'
#define LOWER_CHAR_CASE 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': \
case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': \
case 'u': case 'v': case 'w': case 'x': case 'y': case 'z'
#define HEX_CHAR_CASE 'a': case 'b': case 'c': case 'd': case 'e': case 'f': \
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F'
#if MEM_PRINT
#define MALLOC(mem) (printf("Alloc at %s %zu\n", __FUNCTION__, (size_t)(mem)), malloc_arena(mem))
#define MALLOCS(type) (printf("calloc at %s %zu\n", __FUNCTION__, sizeof(type)), malloc_arena(sizeof(type)))
@@ -74,297 +178,6 @@ void taskqueue_wait_for_completion(TaskQueueRef queue);
#define CALLOCS(type) calloc_arena(sizeof(type))
#endif
#define NUMBER_CHAR_CASE '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9'
static inline bool is_power_of_two(uint64_t x)
{
return x != 0 && (x & (x - 1)) == 0;
}
static inline uint32_t next_highest_power_of_2(uint32_t v)
{
v--;
v |= v >> 1U;
v |= v >> 2U;
v |= v >> 4U;
v |= v >> 8U;
v |= v >> 16U;
v++;
return v;
}
static inline bool is_lower(char c)
{
return c >= 'a' && c <= 'z';
}
static inline bool is_lower_(char c)
{
return c == '_' || (c >= 'a' && c <= 'z');
}
static inline bool is_upper(char c)
{
return c >= 'A' && c <= 'Z';
}
static inline bool is_oct(char c)
{
return c >= '0' && c <= '7';
}
static inline bool is_oct_or_(char c)
{
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '_':
return true;
default:
return false;
}
}
static inline bool is_binary(char c)
{
return c == '0' || c == '1';
}
static inline bool is_binary_or_(char c)
{
switch (c)
{
case '0': case '1': case '_':
return true;
default:
return false;
}
}
static inline bool is_digit_or_(char c)
{
switch (c)
{
case NUMBER_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}
static inline bool is_digit(char c)
{
return c >= '0' && c <= '9';
}
/**
* Convert hex character to nibble
* @param c
* @return value or -1 if invalid.
*/
static inline int char_to_nibble(char c)
{
char conv[256] = {
['0'] = 1,
['1'] = 2,
['2'] = 3,
['3'] = 4,
['4'] = 5,
['5'] = 6,
['6'] = 7,
['7'] = 8,
['8'] = 9,
['9'] = 10,
['A'] = 11,
['B'] = 12,
['C'] = 13,
['D'] = 14,
['E'] = 15,
['F'] = 16,
['a'] = 11,
['b'] = 12,
['c'] = 13,
['d'] = 14,
['e'] = 15,
['f'] = 16,
};
return conv[(unsigned)c] - 1;
}
static inline bool is_hex_or_(char c)
{
switch (c)
{
case NUMBER_CHAR_CASE:
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F':
case '_':
return true;
default:
return false;
}
}
static inline signed char is_valid_escape(char c)
{
switch (c)
{
case 'a':
return '\a';
case 'b':
return '\b';
case 'e':
return 0x1B;
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case 'x':
return 'x';
case 'u':
return 'u';
case 'U':
return 'U';
case '\'':
return '\'';
case '"':
return '"';
case '\\':
return '\\';
case '0':
return '\0';
case 's':
return ' ';
default:
return -1;
}
}
static inline bool is_base64(char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')
|| c == '+' || c == '/';
}
static inline bool is_hex(char c)
{
switch (c)
{
case NUMBER_CHAR_CASE:
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F':
return true;
default:
return false;
}
}
static inline int hex_nibble(char c)
{
static int conv[256] = {
['0'] = 0, ['1'] = 1, ['2'] = 2, ['3'] = 3, ['4'] = 4,
['5'] = 5, ['6'] = 6, ['7'] = 7, ['8'] = 8, ['9'] = 9,
['A'] = 10, ['B'] = 11, ['C'] = 12, ['D'] = 13, ['E'] = 14, ['F'] = 15,
['a'] = 10, ['b'] = 11, ['c'] = 12, ['d'] = 13, ['e'] = 14, ['f'] = 15,
};
return conv[(unsigned char)c];
}
static inline char nibble_hex(int c)
{
static const char *conv = "0123456789ABCDEF";
return conv[c];
}
static inline bool is_whitespace(char c)
{
switch (c)
{
case ' ':
case '\t':
case '\n':
return true;
case '\r':
UNREACHABLE
default:
return false;
}
}
static inline bool is_alphanum_(char c)
{
switch (c)
{
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
case NUMBER_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}
static inline bool is_letter(char c)
{
switch (c)
{
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
return true;
default:
return false;
}
}
INLINE bool is_letter_(char c)
{
return is_letter(c) || c == '_';
}
static inline bool is_number(char c)
{
return c >= '0' && c <= '9';
}
#define FNV1_PRIME 0x01000193u
#define FNV1_SEED 0x811C9DC5u
@@ -396,12 +209,6 @@ static inline VHeader_* vec_new_(size_t element_size, size_t capacity)
return header;
}
static inline uint32_t vec_size(const void *vec)
{
if (!vec) return 0;
const VHeader_ *header = vec;
return header[-1].size;
}
static inline void vec_resize(void *vec, uint32_t new_size)
{
@@ -409,6 +216,7 @@ static inline void vec_resize(void *vec, uint32_t new_size)
VHeader_ *header = vec;
header[-1].size = new_size;
}
static inline void vec_pop(void *vec)
{
assert(vec);
@@ -416,6 +224,7 @@ static inline void vec_pop(void *vec)
VHeader_ *header = vec;
header[-1].size--;
}
static inline void* expand_(void *vec, size_t element_size)
{
VHeader_ *header;
@@ -476,54 +285,6 @@ static inline void* expand_(void *vec, size_t element_size)
#define VECLAST(_vec) (vec_size(_vec) ? (_vec)[vec_size(_vec) - 1] : NULL)
#endif
static inline bool is_all_upper(const char* string)
{
char c;
while ((c = *(string++)) != '\0')
{
if (is_lower(c)) return false;
}
return true;
}
static inline bool is_all_lower(const char* string)
{
char c;
while ((c = *(string++)) != '\0')
{
if (is_upper(c)) return false;
}
return true;
}
#ifndef __printflike
#define __printflike(x, y)
#endif
typedef struct StringSlice_
{
const char *ptr;
size_t len;
} StringSlice;
char *strcat_arena(const char *a, const char *b);
int str_in_list(const char *value, unsigned count, const char** elements);
char *strformat(const char *var, ...) __printflike(1, 2);
StringSlice strnexttok(StringSlice *slice, char separator);
static inline bool slicestrcmp(StringSlice slice, const char *other)
{
if (strlen(other) != slice.len) return false;
return strncmp(slice.ptr, other, slice.len) == 0;
}
static inline StringSlice strtoslice(const char *data)
{
return (StringSlice) { data, strlen(data) };
}
void slicetrim(StringSlice *slice);
#if IS_GCC || IS_CLANG
#define MAX(_a, _b) ({ \
@@ -545,11 +306,258 @@ void slicetrim(StringSlice *slice);
#if PLATFORM_WINDOWS
int asprintf(char **strp, const char *fmt, ...);
int vasprintf(char **strp, const char *fmt, va_list ap);
char *realpath(const char *path, char *resolved_path);
#define mkdir(name, unused) _mkdir(name)
#endif
static inline bool slice_strcmp(StringSlice slice, const char *other)
{
if (strlen(other) != slice.len) return false;
return strncmp(slice.ptr, other, slice.len) == 0;
}
static inline StringSlice slice_from_string(const char *data)
{
return (StringSlice) { data, strlen(data) };
}
static inline uint32_t vec_size(const void *vec)
{
if (!vec) return 0;
const VHeader_ *header = vec;
return header[-1].size;
}
static inline bool is_power_of_two(uint64_t x)
{
return x != 0 && (x & (x - 1)) == 0;
}
static inline uint32_t next_highest_power_of_2(uint32_t v)
{
v--;
v |= v >> 1U;
v |= v >> 2U;
v |= v >> 4U;
v |= v >> 8U;
v |= v >> 16U;
v++;
return v;
}
static inline bool char_is_lower(char c)
{
return c >= 'a' && c <= 'z';
}
static inline bool char_is_lower_(char c)
{
return c == '_' || (c >= 'a' && c <= 'z');
}
static inline bool char_is_upper(char c)
{
return c >= 'A' && c <= 'Z';
}
static inline bool char_is_oct(char c)
{
return c >= '0' && c <= '7';
}
static inline bool char_is_oct_or_(char c)
{
return c == '_' || (c >= '0' && c <= '7');
}
static inline bool char_is_binary(char c)
{
return c == '0' || c == '1';
}
static inline bool char_is_binary_or_(char c)
{
return c == '0' || c == '1' || c == '_';
}
static inline bool char_is_digit_or_(char c)
{
return c == '_' || (c >= '0' && c <= '9');
}
static inline bool char_is_digit(char c)
{
return c >= '0' && c <= '9';
}
static char hex_conv[256] = {
['0'] = 1,
['1'] = 2,
['2'] = 3,
['3'] = 4,
['4'] = 5,
['5'] = 6,
['6'] = 7,
['7'] = 8,
['8'] = 9,
['9'] = 10,
['A'] = 11,
['B'] = 12,
['C'] = 13,
['D'] = 14,
['E'] = 15,
['F'] = 16,
['a'] = 11,
['b'] = 12,
['c'] = 13,
['d'] = 14,
['e'] = 15,
['f'] = 16,
};
static inline int char_hex_to_nibble(char c)
{
return hex_conv[(unsigned)c] - 1;
}
static inline bool char_is_hex_or_(char c)
{
switch (c)
{
case NUMBER_CHAR_CASE:
case HEX_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}
static inline signed char char_is_valid_escape(char c)
{
switch (c)
{
case 'a':
return '\a';
case 'b':
return '\b';
case 'e':
return 0x1B;
case 'f':
return '\f';
case 'n':
return '\n';
case 'r':
return '\r';
case 't':
return '\t';
case 'v':
return '\v';
case 'x':
return 'x';
case 'u':
return 'u';
case 'U':
return 'U';
case '\'':
return '\'';
case '"':
return '"';
case '\\':
return '\\';
case '0':
return '\0';
case 's':
return ' ';
default:
return -1;
}
}
static inline bool char_is_base64(char c)
{
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')
|| c == '+' || c == '/';
}
static inline bool char_is_hex(char c)
{
return hex_conv[(unsigned char)c] != 0;
}
static inline char char_nibble_to_hex(int c)
{
static const char *conv = "0123456789ABCDEF";
return conv[c];
}
static inline bool char_is_whitespace(char c)
{
switch (c)
{
case ' ':
case '\t':
case '\n':
return true;
case '\r':
UNREACHABLE
default:
return false;
}
}
static inline bool char_is_alphanum_(char c)
{
switch (c)
{
case LOWER_CHAR_CASE:
case UPPER_CHAR_CASE:
case NUMBER_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}
static inline bool char_is_lower_alphanum_(char c)
{
switch (c)
{
case LOWER_CHAR_CASE:
case NUMBER_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}
static inline bool char_is_letter(char c)
{
switch (c)
{
case LOWER_CHAR_CASE:
case UPPER_CHAR_CASE:
return true;
default:
return false;
}
}
static inline bool char_is_letter_(char c)
{
switch (c)
{
case LOWER_CHAR_CASE:
case UPPER_CHAR_CASE:
case '_':
return true;
default:
return false;
}
}

View File

@@ -37,13 +37,6 @@ void *calloc_string(size_t len)
return vmem_alloc(&char_arena, len);
}
char *copy_string(const char *start, size_t str_len)
{
char *dst = calloc_string(str_len + 1);
memcpy(dst, start, str_len);
// No need to set the end
return dst;
}
// Simple bump allocator with buckets.
void *calloc_arena(size_t mem)

View File

@@ -8,7 +8,9 @@
#include "lib.h"
#include "stdio.h"
int str_in_list(const char *value, unsigned count, const char** elements)
struct ScratchBuf scratch_buffer;
int str_findlist(const char *value, unsigned count, const char** elements)
{
for (unsigned i = 0; i < count; i++)
{
@@ -17,23 +19,68 @@ int str_in_list(const char *value, unsigned count, const char** elements)
return -1;
}
char *strformat(const char *var, ...)
bool str_has_no_uppercase(const char *string)
{
va_list list;
va_start(list, var);
int len = vsnprintf(NULL, 0, var, list);
va_end(list);
if (len < 1) return "";
va_start(list, var);
char c;
while ((c = *(string++)) != '\0')
{
if (char_is_upper(c)) return false;
}
return true;
}
bool str_is_valid_lowercase_name(const char *string)
{
char c;
// Must start with a lower case
if (!char_is_lower(string[0])) return false;
int length = 0;
while ((c = *(string++)) != '\0')
{
if (!char_is_lower_alphanum_(c)) return false;
if (++length > 127) return false;
}
return true;
}
void str_ellide_in_place(char *string, size_t max_size_shown)
{
size_t len = strlen(string);
if (max_size_shown > len) return;
for (int i = 0; i < 3; i++)
{
string[max_size_shown - i] = '.';
}
string[max_size_shown + 1] = 0;
}
char *str_vprintf(const char *var, va_list list)
{
va_list copy;
va_copy(copy, list);
int len = vsnprintf(NULL, 0, var, copy);
va_end(copy);
if (len < 1)
{
return "";
}
char *buffer = malloc_string((uint32_t)len + 1);
int new_len = vsnprintf(buffer, len + 1, var, list);
va_end(list);
assert(len == new_len);
(void)new_len;
return buffer;
}
const char *str_without_suffix(const char *name, const char *suffix)
char *str_printf(const char *var, ...)
{
va_list list;
va_start(list, var);
char *res = str_vprintf(var, list);
va_end(list);
return res;
}
const char *str_remove_suffix(const char *name, const char *suffix)
{
size_t name_len = strlen(name);
size_t suffix_len = strlen(suffix);
@@ -47,7 +94,7 @@ const char *str_without_suffix(const char *name, const char *suffix)
}
StringSlice strnexttok(StringSlice *slice, char separator)
StringSlice slice_next_token(StringSlice *slice, char separator)
{
for (size_t i = 0; i < slice->len; i++)
{
@@ -65,7 +112,7 @@ StringSlice strnexttok(StringSlice *slice, char separator)
return result;
}
void slicetrim(StringSlice *slice)
void slice_trim(StringSlice *slice)
{
size_t i;
for (i = 0; i < slice->len; i++)
@@ -81,9 +128,54 @@ void slicetrim(StringSlice *slice)
slice->len = i;
}
char *str_trim(char *str)
{
str_trim_end(str);
return (char *)str_trim_start(str);
}
const char *str_trim_start(const char *str)
{
while (str[0] != 0)
{
switch (str[0])
{
case ' ':
case '\t':
case '\n':
case '\r':
str++;
continue;
default:
break;
}
break;
}
return str;
}
char *strcat_arena(const char *a, const char *b)
void str_trim_end(char *str)
{
size_t len = strlen(str);
char *end = str + len - 1;
while (len > 0)
{
switch (*end)
{
case ' ':
case '\t':
case '\n':
case '\r':
len--;
end--;
continue;
default:
end[1] = 0;
return;
}
}
}
char *str_cat(const char *a, const char *b)
{
unsigned a_len = (unsigned)strlen(a);
unsigned b_len = (unsigned)strlen(b);
@@ -94,46 +186,86 @@ char *strcat_arena(const char *a, const char *b)
return buffer;
}
#if PLATFORM_WINDOWS
char *str_copy(const char *start, size_t str_len)
{
char *dst = calloc_string(str_len + 1);
memcpy(dst, start, str_len);
// No need to set the end
return dst;
}
int asprintf(char **strp, const char *fmt, ...)
void scratch_buffer_clear(void)
{
scratch_buffer.len = 0;
}
void scratch_buffer_append_len(const char *string, size_t len)
{
if (len + scratch_buffer.len > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
memcpy(scratch_buffer.str + scratch_buffer.len, string, len);
scratch_buffer.len += len;
}
void scratch_buffer_append(const char *string)
{
scratch_buffer_append_len(string, strlen(string));
}
void scratch_buffer_append_signed_int(int64_t i)
{
uint32_t len_needed = (uint32_t)sprintf(&scratch_buffer.str[scratch_buffer.len], "%lld", (long long)i);
if (scratch_buffer.len + len_needed > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
scratch_buffer.len += len_needed;
}
void scratch_buffer_append_unsigned_int(uint64_t i)
{
uint32_t len_needed = (uint32_t)sprintf(&scratch_buffer.str[scratch_buffer.len], "%llu", (unsigned long long)i);
if (scratch_buffer.len + len_needed > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
scratch_buffer.len += len_needed;
}
void scratch_buffer_printf(const char *format, ...)
{
va_list args;
va_start(args, fmt);
int res = vasprintf(strp, fmt, args);
va_start(args, format);
uint32_t len_needed = (uint32_t)vsprintf(&scratch_buffer.str[scratch_buffer.len], format, args);
if (scratch_buffer.len + len_needed > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
va_end(args);
return res;
scratch_buffer.len += len_needed;
}
int vasnprintf(char **strp, const char *fmt, va_list args)
void scratch_buffer_append_char(char c)
{
va_list args_copy;
va_copy(args_copy, args);
int res = vsprintf(NULL, fmt, args);
if (res < 0) goto END;
char *buf = ccalloc(res + 1, 1);
if (NULL == buf) goto END;
sprintf(buf, fmt, args_copy); // this can't fail, right?
*strp = buf;
END:
va_end(args_copy);
return res;
if (scratch_buffer.len + 1 > MAX_STRING_BUFFER - 1)
{
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
}
scratch_buffer.str[scratch_buffer.len++] = c;
}
int vasprintf(char** ret, const char* fmt, va_list args) {
int length = _vsnprintf(NULL, 0, fmt, args);
if (length < 0) { // check if _vsnprintf failed
return -1;
}
*ret = cmalloc(length + 1);
if (!*ret) { // check if malloc failed
return -1;
}
// Write String
_vsnprintf(*ret, length + 1, fmt, args);
(*ret)[length] = '\0'; // make sure there is a null terminator
return length;
char *scratch_buffer_to_string(void)
{
scratch_buffer.str[scratch_buffer.len] = '\0';
return scratch_buffer.str;
}
char *scratch_buffer_copy(void)
{
return str_copy(scratch_buffer.str, scratch_buffer.len);
}
#endif

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.1.1"
#define COMPILER_VERSION "0.1.2"

View File

@@ -1,4 +1,4 @@
// #target: aarch64-darwin
// #target: macos-aarch64
module test;
struct Large {

View File

@@ -1,4 +1,4 @@
// #target: aarch64-darwin
// #target: macos-aarch64
module test;
define Int8x16 = ichar[<16>];
define Float32x3 = float[<3>];

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
// #opt: --x86vec=avx
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
// #opt: --x86vec=avx512
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
// #opt: --x86vec=sse
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
fn char f0() {

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
struct St12

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
struct Test
{

View File

@@ -1,4 +1,4 @@
// #target: aarch64-linux
// #target: linux-aarch64
module literal_load;
struct Test

View File

@@ -1,4 +1,4 @@
// #target: x64-mingw
// #target: mingw-x64
module literal_load;
struct Test

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
int foo @section("foo, 12345678901234567 "); // #error: Mach-o requires the section to be at the most 16 characters
int bar @section("foo, "); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly?

View File

@@ -1,4 +1,4 @@
// #target: aarch64-linux
// #target: linux-aarch64
module pass_large;

View File

@@ -1,4 +1,4 @@
// #target: x64-mingw
// #target: mingw-x64
module test;
extern fn void printf(char*, ...);
@@ -21,12 +21,12 @@ fn int main()
%Foo = type { [2 x float] }
@Foo = linkonce_odr constant i8 1
$introspect.Foo = comdat any
@introspect.Foo = linkonce constant i8 1
; Function Attrs: nounwind
declare void @printf(i8*, ...) #0
; Function Attrs: nounwind
define x86_regcallcc void @test.test(float %0, float %1) #0 {
entry:
%x = alloca %Foo, align 4

View File

@@ -1,4 +1,4 @@
// #target: riscv64-linux
// #target: linux-riscv64
module test;
struct Large {

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
struct Foo
{

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
struct Abc {
long a;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module unionx64;

View File

@@ -1,4 +1,4 @@
// #target: aarch64-linux
// #target: linux-aarch64
module abi;
struct Vector2 {

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module abi;
struct Vector2 {

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
extern fn void test1_f(void *);

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module array_casts;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module array_literal;
fn double test(uint x)

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
struct Foo

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
struct Connection

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-windows
// #target: windows-x64
fn int foo()
{

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;
fn int foo(double b)

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
struct Foo { int x, y; }

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
fn int strcmp(char *s1, char *s2);

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
extern fn int printf(char *, ...);
extern fn int foo();

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;
char[8192] stack;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module foo;
int x1 = 2 ^ 4;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
extern fn void printf(char*, ...);

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
extern fn void printf(char*, ...);

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;
extern fn void printf(char*, ...);
@@ -34,7 +34,7 @@ fn int main()
source_filename = "test"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-apple-darwin-1"
target triple = "x86_64-apple-darwin"
@test.oeoekgokege = local_unnamed_addr global i32 343432, align 4
@.str = private unnamed_addr constant [7 x i8] c"Hello\0A\00", align 1

View File

@@ -1,4 +1,4 @@
// #target: x64-darwin
// #target: macos-x64
module test;

Some files were not shown because too many files have changed in this diff Show More