mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Compare commits
12 Commits
experiment
...
lld-llvm14
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cf99c2be5c | ||
|
|
50f43b3c71 | ||
|
|
40a0e71b24 | ||
|
|
bbb4bbe570 | ||
|
|
54422fd5e5 | ||
|
|
e08bac422a | ||
|
|
e86cf074c8 | ||
|
|
26cc87d3fc | ||
|
|
0bb2afb0ed | ||
|
|
633eb65e18 | ||
|
|
b717b84046 | ||
|
|
0cf110f763 |
49
.github/workflows/main.yml
vendored
49
.github/workflows/main.yml
vendored
@@ -7,6 +7,36 @@ on:
|
|||||||
branches: [ master ]
|
branches: [ master ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
|
build-msvc:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
# Don't abort runners if a single one fails
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
build_type: [ Release, Debug ]
|
||||||
|
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: cmd
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: CMake
|
||||||
|
run: |
|
||||||
|
cmake -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||||
|
cmake --build build
|
||||||
|
|
||||||
|
- name: Build testproject
|
||||||
|
run: |
|
||||||
|
cd resources/testproject
|
||||||
|
../../build/c3c run --debug-log
|
||||||
|
|
||||||
|
- name: run compiler tests
|
||||||
|
run: |
|
||||||
|
cd test
|
||||||
|
python3 src/tester.py ../build/c3c.exe test_suite/
|
||||||
|
|
||||||
build-msys2-mingw:
|
build-msys2-mingw:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
strategy:
|
strategy:
|
||||||
@@ -38,13 +68,14 @@ jobs:
|
|||||||
- name: Build testproject
|
- name: Build testproject
|
||||||
run: |
|
run: |
|
||||||
cd resources/testproject
|
cd resources/testproject
|
||||||
../../build/c3c build --debug-log
|
../../build/c3c run --debug-log
|
||||||
|
|
||||||
- name: run compiler tests
|
- name: run compiler tests
|
||||||
run: |
|
run: |
|
||||||
cd test
|
cd test
|
||||||
python3 src/tester.py ../build/c3c.exe test_suite/
|
python3 src/tester.py ../build/c3c.exe test_suite/
|
||||||
|
|
||||||
|
|
||||||
build-msys2-clang:
|
build-msys2-clang:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
#if: ${{ false }}
|
#if: ${{ false }}
|
||||||
@@ -73,7 +104,7 @@ jobs:
|
|||||||
- name: Build testproject
|
- name: Build testproject
|
||||||
run: |
|
run: |
|
||||||
cd resources/testproject
|
cd resources/testproject
|
||||||
../../build/c3c build --debug-log
|
../../build/c3c run --debug-log
|
||||||
|
|
||||||
- name: run compiler tests
|
- name: run compiler tests
|
||||||
run: |
|
run: |
|
||||||
@@ -118,7 +149,12 @@ jobs:
|
|||||||
- name: Build testproject
|
- name: Build testproject
|
||||||
run: |
|
run: |
|
||||||
cd resources/testproject
|
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
|
- name: run compiler tests
|
||||||
run: |
|
run: |
|
||||||
@@ -150,7 +186,12 @@ jobs:
|
|||||||
- name: Build testproject
|
- name: Build testproject
|
||||||
run: |
|
run: |
|
||||||
cd resources/testproject
|
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
|
- name: run compiler tests
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
120
CMakeLists.txt
120
CMakeLists.txt
@@ -1,10 +1,17 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
project(c3c)
|
project(c3c)
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
|
set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
|
||||||
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
|
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION DEC)
|
||||||
|
set(CMAKE_C_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1")
|
||||||
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3")
|
||||||
|
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3")
|
||||||
|
|
||||||
set(C3_LLVM_VERSION "auto" CACHE STRING "Use LLVM version [default: auto]")
|
set(C3_LLVM_VERSION "auto" CACHE STRING "Use LLVM version [default: auto]")
|
||||||
option(C3_USE_MIMALLOC "Use built-in mimalloc" OFF)
|
option(C3_USE_MIMALLOC "Use built-in mimalloc" OFF)
|
||||||
set(C3_MIMALLOC_TAG "v1.7.3" CACHE STRING "Used version of mimalloc")
|
set(C3_MIMALLOC_TAG "v1.7.3" CACHE STRING "Used version of mimalloc")
|
||||||
@@ -23,29 +30,49 @@ if(C3_USE_MIMALLOC)
|
|||||||
FetchContent_MakeAvailable(mimalloc)
|
FetchContent_MakeAvailable(mimalloc)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT C3_LLVM_VERSION STREQUAL "auto")
|
if (NOT C3_LLVM_VERSION STREQUAL "auto")
|
||||||
if(${C3_LLVM_VERSION} VERSION_LESS 12 OR ${C3_LLVM_VERSION} VERSION_GREATER 15)
|
if (${C3_LLVM_VERSION} VERSION_LESS 12 OR ${C3_LLVM_VERSION} VERSION_GREATER 15)
|
||||||
message(FATAL_ERROR "LLVM ${C3_LLVM_VERSION} is not supported!")
|
message(FATAL_ERROR "LLVM ${C3_LLVM_VERSION} is not supported!")
|
||||||
endif()
|
endif()
|
||||||
find_package(LLVM ${C3_LLVM_VERSION} REQUIRED CONFIG)
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
|
if (C3_LLVM_VERSION STREQUAL "auto")
|
||||||
|
set(C3_LLVM_VERSION "13")
|
||||||
|
endif()
|
||||||
|
FetchContent_Declare(
|
||||||
|
LLVM_Windows
|
||||||
|
URL https://github.com/c3lang/win-llvm/releases/download/lld-llvm${C3_LLVM_VERSION}-release/llvm-${C3_LLVM_VERSION}.0.0-windows-amd64-msvc16-msvcrt.7z
|
||||||
|
)
|
||||||
|
FetchContent_Declare(
|
||||||
|
LLVM_Windows_debug
|
||||||
|
URL https://github.com/c3lang/win-llvm/releases/download/lld-llvm${C3_LLVM_VERSION}-release/llvm-${C3_LLVM_VERSION}.0.0-windows-amd64-msvc16-msvcrt-dbg.7z
|
||||||
|
)
|
||||||
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
|
message("Loading Windows LLVM debug libraries...")
|
||||||
|
FetchContent_MakeAvailable(LLVM_Windows_debug)
|
||||||
|
set(CMAKE_SYSTEM_PREFIX_PATH ${llvm_windows_debug_SOURCE_DIR} ${CMAKE_SYSTEM_PREFIX_PATH})
|
||||||
|
else()
|
||||||
|
message("Loading Windows LLVM libraries...")
|
||||||
|
FetchContent_MakeAvailable(LLVM_Windows)
|
||||||
|
set(CMAKE_SYSTEM_PREFIX_PATH ${llvm_windows_SOURCE_DIR} ${CMAKE_SYSTEM_PREFIX_PATH})
|
||||||
|
endif()
|
||||||
|
find_package(LLVM REQUIRED CONFIG)
|
||||||
|
find_package(LLD REQUIRED CONFIG)
|
||||||
else()
|
else()
|
||||||
find_package(LLVM REQUIRED CONFIG)
|
if (NOT C3_LLVM_VERSION STREQUAL "auto")
|
||||||
|
find_package(LLVM ${C3_LLVM_VERSION} REQUIRED CONFIG)
|
||||||
|
else()
|
||||||
|
find_package(LLVM REQUIRED CONFIG)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||||
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||||
message(STATUS "Libraries located in: ${LLVM_LIBRARY_DIRS}")
|
message(STATUS "Libraries located in: ${LLVM_LIBRARY_DIRS}")
|
||||||
|
|
||||||
include_directories(${LLVM_INCLUDE_DIRS})
|
include_directories(${LLVM_INCLUDE_DIRS})
|
||||||
add_definitions(${LLVM_DEFINITIONS})
|
add_definitions(${LLVM_DEFINITIONS})
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O1")
|
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -gdwarf-3 -O3")
|
|
||||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -gdwarf-3")
|
|
||||||
|
|
||||||
set(LLVM_LINK_COMPONENTS
|
set(LLVM_LINK_COMPONENTS
|
||||||
AllTargetsAsmParsers
|
AllTargetsAsmParsers
|
||||||
AllTargetsCodeGens
|
AllTargetsCodeGens
|
||||||
@@ -73,7 +100,7 @@ set(LLVM_LINK_COMPONENTS
|
|||||||
Target
|
Target
|
||||||
TransformUtils
|
TransformUtils
|
||||||
WindowsManifest
|
WindowsManifest
|
||||||
)
|
)
|
||||||
|
|
||||||
if (${LLVM_PACKAGE_VERSION} VERSION_GREATER 14.1)
|
if (${LLVM_PACKAGE_VERSION} VERSION_GREATER 14.1)
|
||||||
set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} WindowsDriver)
|
set(LLVM_LINK_COMPONENTS ${LLVM_LINK_COMPONENTS} WindowsDriver)
|
||||||
@@ -83,22 +110,27 @@ llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})
|
|||||||
|
|
||||||
file(COPY ${CMAKE_SOURCE_DIR}/lib DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY ${CMAKE_SOURCE_DIR}/lib DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
|
|
||||||
# These don't seem to be reliable on windows.
|
# These don't seem to be reliable on windows.
|
||||||
if(UNIX)
|
if(true)
|
||||||
message(STATUS "using find_library")
|
message(STATUS "using find_library")
|
||||||
# find_library(TB_LIB NAMES tinybackend.a PATHS ${CMAKE_SOURCE_DIR}/resources/tblib)
|
# 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_COFF NAMES lldCOFF.lib lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_COMMON NAMES lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_COMMON NAMES lldCommon.lib lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_ELF NAMES lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_ELF NAMES lldELF.lib lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_MACHO NAMES lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
|
if (${LLVM_PACKAGE_VERSION} VERSION_LESS 14)
|
||||||
find_library(LLD_MINGW NAMES lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_MACHO NAMES lldMachO2.lib lldMachO2.a liblldMachO2.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_WASM NAMES lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
|
else()
|
||||||
|
find_library(LLD_MACHO NAMES lldMachO.lib lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
|
endif()
|
||||||
|
find_library(LLD_MINGW NAMES lldMinGW.lib lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
|
find_library(LLD_WASM NAMES lldWasm.lib lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
|
|
||||||
if (${LLVM_PACKAGE_VERSION} VERSION_LESS 14)
|
if (${LLVM_PACKAGE_VERSION} VERSION_LESS 14)
|
||||||
find_library(LLD_CORE NAMES lldCore.a liblldCore.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_CORE NAMES lldCore.lib lldCore.a liblldCore.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_DRIVER NAMES lldDriver.a liblldDriver.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_DRIVER NAMES lldDriver.lib lldDriver.a liblldDriver.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_READER_WRITER NAMES lldReaderWriter.a liblldReaderWriter.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_READER_WRITER NAMES lldReaderWriter.lib lldReaderWriter.a liblldReaderWriter.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_YAML NAMES lldYAML.a liblldYAML.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_YAML NAMES lldYAML.lib lldYAML.a liblldYAML.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(lld_libs
|
set(lld_libs
|
||||||
@@ -113,9 +145,18 @@ if(UNIX)
|
|||||||
${LLD_YAML}
|
${LLD_YAML}
|
||||||
${LLD_CORE}
|
${LLD_CORE}
|
||||||
)
|
)
|
||||||
message(STATUS "linking to llvm libs ${llvm_libs} ${lld_libs}")
|
if(APPLE)
|
||||||
endif()
|
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}")
|
message(STATUS "Found LLD ${lld_libs}")
|
||||||
|
|
||||||
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
|
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
|
||||||
@@ -138,6 +179,7 @@ add_executable(c3c
|
|||||||
src/compiler/float.c
|
src/compiler/float.c
|
||||||
src/compiler/headers.c
|
src/compiler/headers.c
|
||||||
src/compiler/lexer.c
|
src/compiler/lexer.c
|
||||||
|
src/compiler/libraries.c
|
||||||
src/compiler/linker.c
|
src/compiler/linker.c
|
||||||
src/compiler/llvm_codegen.c
|
src/compiler/llvm_codegen.c
|
||||||
src/compiler/llvm_codegen_c_abi_aarch64.c
|
src/compiler/llvm_codegen_c_abi_aarch64.c
|
||||||
@@ -196,11 +238,12 @@ add_executable(c3c
|
|||||||
src/utils/vmem.h
|
src/utils/vmem.h
|
||||||
src/utils/whereami.c
|
src/utils/whereami.c
|
||||||
src/compiler/decltable.c
|
src/compiler/decltable.c
|
||||||
|
src/compiler/mac_support.c
|
||||||
src/compiler/tilde_codegen_storeload.c
|
src/compiler/tilde_codegen_storeload.c
|
||||||
src/compiler/llvm_codegen_storeload.c
|
src/compiler/llvm_codegen_storeload.c
|
||||||
src/compiler/tilde_codegen_expr.c
|
src/compiler/tilde_codegen_expr.c
|
||||||
src/compiler/tilde_codegen_stmt.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")
|
if(NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
message(STATUS "using gcc/clang warning switches")
|
message(STATUS "using gcc/clang warning switches")
|
||||||
@@ -219,20 +262,15 @@ target_include_directories(c3c_wrappers PRIVATE
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if(UNIX)
|
target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs})
|
||||||
target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs})
|
target_link_libraries(c3c ${llvm_libs} c3c_wrappers ${lld_libs})
|
||||||
target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${lld_libs})
|
|
||||||
# target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${TB_LIB} ${lld_libs})
|
# target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${TB_LIB} ${lld_libs})
|
||||||
if(C3_USE_MIMALLOC)
|
if(C3_USE_MIMALLOC)
|
||||||
target_link_libraries(c3c m mimalloc-static)
|
target_link_libraries(c3c m mimalloc-static)
|
||||||
endif()
|
endif()
|
||||||
else()
|
if(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
# todo: maybe get this from llvm-config somehow? it should be in LLVM_DIR\..\..\..\bin I think.
|
target_link_libraries(c3c Advapi32)
|
||||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -LIBPATH:C:\\llvm\\llvm\\build\\Release\\lib") # needed for lldCommon.lib
|
target_link_options(c3c_wrappers PRIVATE nowarn)
|
||||||
#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)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ fn void test()
|
|||||||
|
|
||||||
### Current status
|
### Current status
|
||||||
|
|
||||||
The current version of the compiler is alpha release 0.1.0.
|
The current version of the compiler is alpha release 0.1.
|
||||||
|
|
||||||
It's possible to try out the current C3 compiler in the browser: https://ide.judge0.com/ – this is courtesy of the
|
It's possible to try out the current C3 compiler in the browser: https://ide.judge0.com/ – this is courtesy of the
|
||||||
developer of Judge0.
|
developer of Judge0.
|
||||||
|
|||||||
167
resources/testfragments/raylibtest.c3
Normal file
167
resources/testfragments/raylibtest.c3
Normal 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!");
|
||||||
|
}
|
||||||
@@ -9,5 +9,5 @@ fn int main()
|
|||||||
printf("Hello World!\n");
|
printf("Hello World!\n");
|
||||||
bar::test();
|
bar::test();
|
||||||
printf("Hello double: %d\n", test_doubler(11));
|
printf("Hello double: %d\n", test_doubler(11));
|
||||||
return 1;
|
return 17;
|
||||||
}
|
}
|
||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <utils/lib.h>
|
#include <utils/lib.h>
|
||||||
#include "../utils/whereami.h"
|
#include "../utils/whereami.h"
|
||||||
|
|
||||||
|
extern int llvm_version_major;
|
||||||
|
|
||||||
static int arg_index;
|
static int arg_index;
|
||||||
static int arg_count;
|
static int arg_count;
|
||||||
@@ -23,30 +24,30 @@ extern const char* llvm_version;
|
|||||||
extern const char* llvm_target;
|
extern const char* llvm_target;
|
||||||
|
|
||||||
char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
|
char *arch_os_target[ARCH_OS_TARGET_LAST + 1] = {
|
||||||
[X86_FREEBSD] = "x86-freebsd",
|
[WINDOWS_X86] = "windows-x86",
|
||||||
[X86_OPENBSD] = "x86-openbsd",
|
[WINDOWS_X64] = "windows-x64",
|
||||||
[X86_NETBSD] = "x86-netbsd",
|
[MINGW_X64] = "mingw-x64",
|
||||||
[X86_MCU] = "x86-mcu",
|
[MACOS_X64] = "macos-x64",
|
||||||
[X86_ELF] = "x86-elf",
|
[MACOS_AARCH64] = "macos-aarch64",
|
||||||
[X86_WINDOWS] = "x86-windows",
|
[LINUX_X86] = "linux-x86",
|
||||||
[X86_LINUX] = "x86-linux",
|
[LINUX_X64] = "linux-x64",
|
||||||
[X64_DARWIN] = "x64-darwin",
|
[LINUX_AARCH64] = "linux-aarch64",
|
||||||
[X64_LINUX] = "x64-linux",
|
[LINUX_RISCV32] = "linux-riscv32",
|
||||||
[X64_WINDOWS] = "x64-windows",
|
[LINUX_RISCV64] = "linux-riscv64",
|
||||||
[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",
|
|
||||||
[WASM32] = "wasm32",
|
[WASM32] = "wasm32",
|
||||||
[WASM64] = "wasm64",
|
[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__)
|
#define EOUTPUT(string, ...) fprintf(stderr, string "\n", ##__VA_ARGS__)
|
||||||
@@ -74,7 +75,8 @@ static void usage(void)
|
|||||||
OUTPUT("Options:");
|
OUTPUT("Options:");
|
||||||
OUTPUT(" --tinybackend - Use the TinyBackend for compilation.");
|
OUTPUT(" --tinybackend - Use the TinyBackend for compilation.");
|
||||||
OUTPUT(" --stdlib <dir> - Use this directory as the C3 standard library path.");
|
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(" --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(" --template <template> - Use a different template: \"lib\", \"static-lib\" or a path.");
|
||||||
OUTPUT(" --about - Prints a short description of C3.");
|
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> - Link with the library provided.");
|
||||||
OUTPUT(" -L <library dir> - Append the directory to the linker search paths.");
|
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(" -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("");
|
||||||
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE");
|
OUTPUT(" --reloc=<option> - Relocation model: none, pic, PIC, pie, PIE");
|
||||||
OUTPUT(" --x86vec=<option> - Set max level of vector instructions: none, mmx, sse, avx, avx512.");
|
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-attributes - List all attributes.");
|
||||||
OUTPUT(" --list-builtins - List all builtins.");
|
OUTPUT(" --list-builtins - List all builtins.");
|
||||||
OUTPUT(" --list-precedence - List operator precedence order.");
|
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
|
#ifndef NDEBUG
|
||||||
OUTPUT(" --debug-log - Print debug logging to stdout.");
|
OUTPUT(" --debug-log - Print debug logging to stdout.");
|
||||||
#endif
|
#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)
|
static int parse_multi_option(const char *start, unsigned count, const char** elements)
|
||||||
{
|
{
|
||||||
const char *arg = current_arg;
|
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);
|
if (select < 0) error_exit("error: %.*s invalid option '%s' given.", (int)(start - arg), start, arg);
|
||||||
return select;
|
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.");
|
if (at_end() || next_is_opt()) error_exit("error: -l needs a library name.");
|
||||||
const char *lib = next_arg();
|
const char *lib = next_arg();
|
||||||
const char *framework = str_without_suffix(lib, ".framework");
|
const char *framework = str_remove_suffix(lib, ".framework");
|
||||||
if (framework)
|
if (framework)
|
||||||
{
|
{
|
||||||
add_linker_arg(options, "-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);
|
options->symtab_size = next_highest_power_of_2(symtab);
|
||||||
return;
|
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"))
|
if (match_longopt("version"))
|
||||||
{
|
{
|
||||||
print_version();
|
print_version();
|
||||||
@@ -580,11 +601,41 @@ static void parse_option(BuildOptions *options)
|
|||||||
options->panicfn = next_arg();
|
options->panicfn = next_arg();
|
||||||
return;
|
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 (match_longopt("lib"))
|
||||||
{
|
{
|
||||||
if (at_end() || next_is_opt()) error_exit("error: --lib needs a directory.");
|
if (at_end() || next_is_opt()) error_exit("error: --lib needs a name.");
|
||||||
if (options->lib_count == MAX_LIB_DIRS) error_exit("Max %d libraries may be specified.", MAX_LIB_DIRS);
|
const char *name = next_arg();
|
||||||
options->lib_dir[options->lib_count++] = check_dir(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;
|
return;
|
||||||
}
|
}
|
||||||
if (match_longopt("test"))
|
if (match_longopt("test"))
|
||||||
@@ -645,6 +696,7 @@ BuildOptions parse_arguments(int argc, const char *argv[])
|
|||||||
.reloc_model = RELOC_DEFAULT,
|
.reloc_model = RELOC_DEFAULT,
|
||||||
.backend = BACKEND_LLVM,
|
.backend = BACKEND_LLVM,
|
||||||
.x86_vector_capability = X86VECTOR_DEFAULT,
|
.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||||
|
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||||
.files = NULL
|
.files = NULL
|
||||||
};
|
};
|
||||||
for (int i = DIAG_NONE; i < DIAG_WARNING_TYPE; i++)
|
for (int i = DIAG_NONE; i < DIAG_WARNING_TYPE; i++)
|
||||||
|
|||||||
@@ -144,6 +144,20 @@ static const char *vector_capability[5] = {
|
|||||||
[X86VECTOR_AVX512] = "avx512",
|
[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
|
typedef enum
|
||||||
{
|
{
|
||||||
RELOC_DEFAULT = -1,
|
RELOC_DEFAULT = -1,
|
||||||
@@ -173,44 +187,53 @@ typedef enum
|
|||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
ARCH_OS_TARGET_DEFAULT = 0,
|
ARCH_OS_TARGET_DEFAULT = 0,
|
||||||
X86_FREEBSD,
|
LINUX_X86,
|
||||||
X86_OPENBSD,
|
LINUX_X64,
|
||||||
X86_NETBSD,
|
WINDOWS_X86,
|
||||||
X86_LINUX,
|
WINDOWS_X64,
|
||||||
X86_WINDOWS,
|
MINGW_X64,
|
||||||
X86_MCU,
|
MACOS_X64,
|
||||||
X86_ELF,
|
MACOS_AARCH64,
|
||||||
X64_DARWIN,
|
LINUX_AARCH64,
|
||||||
X64_LINUX,
|
LINUX_RISCV32,
|
||||||
X64_NETBSD,
|
LINUX_RISCV64,
|
||||||
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,
|
|
||||||
WASM32,
|
WASM32,
|
||||||
WASM64,
|
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;
|
} ArchOsTarget;
|
||||||
|
|
||||||
typedef struct BuildOptions_
|
typedef struct BuildOptions_
|
||||||
{
|
{
|
||||||
const char* lib_dir[MAX_LIB_DIRS];
|
const char *lib_dir[MAX_LIB_DIRS];
|
||||||
const char* linker_args[MAX_LIB_DIRS];
|
int lib_dir_count;
|
||||||
const char* linker_lib_dir[MAX_LIB_DIRS];
|
const char *libs[MAX_LIB_DIRS];
|
||||||
const char* linker_libs[MAX_LIB_DIRS];
|
|
||||||
const char* std_lib_dir;
|
|
||||||
int lib_count;
|
int lib_count;
|
||||||
|
const char* linker_args[MAX_LIB_DIRS];
|
||||||
int linker_arg_count;
|
int linker_arg_count;
|
||||||
|
const char* linker_lib_dir[MAX_LIB_DIRS];
|
||||||
int linker_lib_dir_count;
|
int linker_lib_dir_count;
|
||||||
|
const char* linker_libs[MAX_LIB_DIRS];
|
||||||
int linker_lib_count;
|
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;
|
int build_threads;
|
||||||
const char** files;
|
const char** files;
|
||||||
const char* output_name;
|
const char* output_name;
|
||||||
@@ -231,6 +254,7 @@ typedef struct BuildOptions_
|
|||||||
bool emit_bitcode;
|
bool emit_bitcode;
|
||||||
bool test_mode;
|
bool test_mode;
|
||||||
bool no_stdlib;
|
bool no_stdlib;
|
||||||
|
bool force_linker;
|
||||||
const char *panicfn;
|
const char *panicfn;
|
||||||
RelocModel reloc_model;
|
RelocModel reloc_model;
|
||||||
X86VectorCapability x86_vector_capability;
|
X86VectorCapability x86_vector_capability;
|
||||||
@@ -253,15 +277,35 @@ typedef enum
|
|||||||
TARGET_TYPE_TEST
|
TARGET_TYPE_TEST
|
||||||
} TargetType;
|
} 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
|
typedef struct
|
||||||
{
|
{
|
||||||
TargetType type;
|
TargetType type;
|
||||||
|
Library **library_list;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *version;
|
const char *version;
|
||||||
const char *langrev;
|
const char *langrev;
|
||||||
const char **source_dirs;
|
const char **source_dirs;
|
||||||
const char **sources;
|
const char **sources;
|
||||||
const char **libraries;
|
const char **libdirs;
|
||||||
|
const char **libs;
|
||||||
|
const char **linker_libdirs;
|
||||||
const char *cpu;
|
const char *cpu;
|
||||||
const char **link_args;
|
const char **link_args;
|
||||||
bool run_after_compile : 1;
|
bool run_after_compile : 1;
|
||||||
@@ -275,6 +319,7 @@ typedef struct
|
|||||||
bool no_stdlib : 1;
|
bool no_stdlib : 1;
|
||||||
bool emit_object_files : 1;
|
bool emit_object_files : 1;
|
||||||
bool no_link : 1;
|
bool no_link : 1;
|
||||||
|
bool force_linker : 1;
|
||||||
OptimizationLevel optimization_level;
|
OptimizationLevel optimization_level;
|
||||||
SizeOptimizationLevel size_optimization_level;
|
SizeOptimizationLevel size_optimization_level;
|
||||||
DebugInfo debug_info;
|
DebugInfo debug_info;
|
||||||
@@ -296,6 +341,15 @@ typedef struct
|
|||||||
bool trap_on_wrap : 1;
|
bool trap_on_wrap : 1;
|
||||||
bool safe_mode : 1;
|
bool safe_mode : 1;
|
||||||
} feature;
|
} feature;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char *sdk;
|
||||||
|
} macos;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
const char *sdk;
|
||||||
|
WinCrtLinking crt_linking;
|
||||||
|
} win;
|
||||||
} BuildTarget;
|
} BuildTarget;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,58 +14,54 @@ void load_library_files(void) {}
|
|||||||
void load_files(void) {}
|
void load_files(void) {}
|
||||||
|
|
||||||
#if defined(_M_X64) || defined(_M_AMD64)
|
#if defined(_M_X64) || defined(_M_AMD64)
|
||||||
#if defined(__MINGW32__)
|
ArchOsTarget default_target = WINDOWS_X64;
|
||||||
ArchOsTarget default_target = X64_WINDOWS_GNU;
|
|
||||||
#else
|
|
||||||
ArchOsTarget default_target = X64_WINDOWS;
|
|
||||||
#endif
|
|
||||||
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
#elif defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
ArchOsTarget default_target = X64_DARWIN;
|
ArchOsTarget default_target = MACOS_X64;
|
||||||
#elif defined(__linux__) && __linux__
|
#elif defined(__linux__) && __linux__
|
||||||
ArchOsTarget default_target = X64_LINUX;
|
ArchOsTarget default_target = LINUX_X64;
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
ArchOsTarget default_target = X64_NETBSD;
|
ArchOsTarget default_target = NETBSD_X64;
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
ArchOsTarget default_target = X64_FREEBSD;
|
ArchOsTarget default_target = FREEBSD_X64;
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
ArchOsTarget default_target = X64_OPENBSD;
|
ArchOsTarget default_target = OPENBSD_X64;
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = X64_ELF;
|
ArchOsTarget default_target = ELF_X64;
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__aarch64__) || defined(_M_ARM64)
|
#elif defined(__aarch64__) || defined(_M_ARM64)
|
||||||
#if defined(__MACH__)
|
#if defined(__MACH__)
|
||||||
ArchOsTarget default_target = AARCH64_DARWIN;
|
ArchOsTarget default_target = MACOS_AARCH64;
|
||||||
#elif defined(__linux__) && __linux__
|
#elif defined(__linux__) && __linux__
|
||||||
ArchOsTarget default_target = AARCH64_LINUX;
|
ArchOsTarget default_target = LINUX_AARCH64;
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = AARCH64_ELF;
|
ArchOsTarget default_target = ELF_AARCH64;
|
||||||
#endif
|
#endif
|
||||||
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
|
#elif defined(i386) || defined(__i386__) || defined(__i386) || defined(_M_IX86)
|
||||||
#if defined(__linux__) && __linux__
|
#if defined(__linux__) && __linux__
|
||||||
ArchOsTarget default_target = X86_LINUX;
|
ArchOsTarget default_target = LINUX_X86;
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__)
|
||||||
ArchOsTarget default_target = X86_FREEBSD;
|
ArchOsTarget default_target = FREEBSD_X86;
|
||||||
#elif defined(__OpenBSD__)
|
#elif defined(__OpenBSD__)
|
||||||
ArchOsTarget default_target = X86_OPENBSD;
|
ArchOsTarget default_target = OPENBSD_X86;
|
||||||
#elif defined(__NetBSD__)
|
#elif defined(__NetBSD__)
|
||||||
ArchOsTarget default_target = X86_NETBSD;
|
ArchOsTarget default_target = NETBSD_X86;
|
||||||
#elif defined(_MSC_VER) && _MSC_VER
|
#elif defined(_MSC_VER) && _MSC_VER
|
||||||
ArchOsTarget default_target = X86_WINDOWS;
|
ArchOsTarget default_target = WINDOWS_X86;
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = X86_ELF;
|
ArchOsTarget default_target = ELF_X86;
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__riscv32)
|
#elif defined(__riscv32)
|
||||||
#if defined(__linux__) && __linux__
|
#if defined(__linux__) && __linux__
|
||||||
ArchOsTarget default_target = RISCV32_LINUX;
|
ArchOsTarget default_target = LINUX_RISCV32;
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = RISCV32_ELF;
|
ArchOsTarget default_target = ELF_RISCV32;
|
||||||
#endif
|
#endif
|
||||||
#elif defined(__riscv64)
|
#elif defined(__riscv64)
|
||||||
#if defined(__linux__) && __linux__
|
#if defined(__linux__) && __linux__
|
||||||
ArchOsTarget default_target = RISCV64_LINUX;
|
ArchOsTarget default_target = LINUX_RISCV64;
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = RISCV64_ELF;
|
ArchOsTarget default_target = ELF_RISCV64;
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
ArchOsTarget default_target = ARCH_OS_TARGET_DEFAULT;
|
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->no_stdlib = options->no_stdlib;
|
||||||
target->emit_llvm = options->emit_llvm;
|
target->emit_llvm = options->emit_llvm;
|
||||||
|
target->force_linker = options->force_linker;
|
||||||
target->panicfn = options->panicfn;
|
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)
|
if (options->x86_vector_capability != X86VECTOR_DEFAULT)
|
||||||
{
|
{
|
||||||
target->feature.x86_vector_capability = options->x86_vector_capability;
|
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_llvm = false;
|
||||||
target->emit_object_files = 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)
|
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,
|
.arch_os_target = ARCH_OS_TARGET_DEFAULT,
|
||||||
.reloc_model = RELOC_DEFAULT,
|
.reloc_model = RELOC_DEFAULT,
|
||||||
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||||
|
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||||
};
|
};
|
||||||
update_build_target_from_options(target, options);
|
update_build_target_from_options(target, options);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ static int get_valid_string_setting(JSONObject *json, const char *key, const cha
|
|||||||
}
|
}
|
||||||
if (value->type == J_STRING)
|
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;
|
if (res >= 0) return res + first_result;
|
||||||
}
|
}
|
||||||
error_exit("%s had an invalid value for '%s', expected %s", category, key, expected);
|
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 *langrev = get_valid_string(json, "langrev", type, false);
|
||||||
const char **source_dirs = get_valid_array(json, "sources", type, target->source_dirs == NULL);
|
const char **source_dirs = get_valid_array(json, "sources", type, target->source_dirs == NULL);
|
||||||
const char **libraries = get_valid_array(json, "libs", type, false);
|
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] = {
|
static const char *debug_infos[3] = {
|
||||||
[DEBUG_INFO_FULL] = "full",
|
[DEBUG_INFO_FULL] = "full",
|
||||||
[DEBUG_INFO_NONE] = "none",
|
[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);
|
long symtab_size = get_valid_integer(json, "symtab", type, false);
|
||||||
const char *cpu = get_valid_string(json, "cpu", 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 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");
|
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);
|
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;
|
target->panicfn = panicfn;
|
||||||
if (cc) target->cc = cc;
|
if (cc) target->cc = cc;
|
||||||
if (cflags) target->cflags = cflags;
|
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 (version) target->version = version;
|
||||||
if (langrev) target->langrev = langrev;
|
if (langrev) target->langrev = langrev;
|
||||||
if (source_dirs) target->source_dirs = source_dirs;
|
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 (info > -1) target->debug_info = info;
|
||||||
if (cpu) target->cpu = cpu;
|
if (cpu) target->cpu = cpu;
|
||||||
|
if (wincrt > -1) target->win.crt_linking = (WinCrtLinking)wincrt;
|
||||||
if (reloc > -1) target->reloc_model = (RelocModel)reloc;
|
if (reloc > -1) target->reloc_model = (RelocModel)reloc;
|
||||||
if (x86vec > -1) target->feature.x86_vector_capability = x86vec;
|
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);
|
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);
|
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.trap_on_wrap = false,
|
||||||
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
.feature.x86_vector_capability = X86VECTOR_DEFAULT,
|
||||||
.feature.safe_mode = true,
|
.feature.safe_mode = true,
|
||||||
|
.win.crt_linking = WIN_CRT_DEFAULT,
|
||||||
};
|
};
|
||||||
load_into_build_target(project_data, "default target", &default_target);
|
load_into_build_target(project_data, "default target", &default_target);
|
||||||
JSONObject *targets_json = json_obj_get(project_data, "targets");
|
JSONObject *targets_json = json_obj_get(project_data, "targets");
|
||||||
@@ -266,7 +282,7 @@ Project *project_load(void)
|
|||||||
{
|
{
|
||||||
Project *project = CALLOCS(Project);
|
Project *project = CALLOCS(Project);
|
||||||
size_t size;
|
size_t size;
|
||||||
char *read = read_file(PROJECT_JSON, &size);
|
char *read = file_read_all(PROJECT_JSON, &size);
|
||||||
JsonParser parser;
|
JsonParser parser;
|
||||||
json_init_string(&parser, read, &malloc_arena);
|
json_init_string(&parser, read, &malloc_arena);
|
||||||
JSONObject *json = json_parse(&parser);
|
JSONObject *json = json_parse(&parser);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ void create_project(BuildOptions *build_options)
|
|||||||
{
|
{
|
||||||
char c = build_options->project_name[i];
|
char c = build_options->project_name[i];
|
||||||
if (c == '\0') break;
|
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);
|
fprintf(stderr, "'%s' is not a valid project name.\n", build_options->project_name);
|
||||||
exit_compiler(EXIT_FAILURE);
|
exit_compiler(EXIT_FAILURE);
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ UNUSED Int128 i128_from_hexstrl(const char *str, const char *end)
|
|||||||
while (str != end)
|
while (str != end)
|
||||||
{
|
{
|
||||||
c = *(str++);
|
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;
|
return x;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,14 +126,18 @@ void thread_compile_task_tb(void *compile_data)
|
|||||||
|
|
||||||
static const char *active_target_name(void)
|
static const char *active_target_name(void)
|
||||||
{
|
{
|
||||||
if (active_target.name) return active_target.name;
|
|
||||||
switch (active_target.arch_os_target)
|
switch (active_target.arch_os_target)
|
||||||
{
|
{
|
||||||
case X86_WINDOWS:
|
case WINDOWS_X86:
|
||||||
case X64_WINDOWS:
|
case WINDOWS_X64:
|
||||||
case X64_WINDOWS_GNU:
|
case MINGW_X64:
|
||||||
|
if (active_target.name)
|
||||||
|
{
|
||||||
|
return str_cat(active_target.name, ".exe");
|
||||||
|
}
|
||||||
return "a.exe";
|
return "a.exe";
|
||||||
default:
|
default:
|
||||||
|
if (active_target.name) return active_target.name;
|
||||||
return "a.out";
|
return "a.out";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -271,7 +275,7 @@ void compiler_compile(void)
|
|||||||
for (int i = 0; i < cfiles; i++)
|
for (int i = 0; i < cfiles; i++)
|
||||||
{
|
{
|
||||||
char *filename = NULL;
|
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);
|
assert(split_worked);
|
||||||
size_t len = strlen(filename);
|
size_t len = strlen(filename);
|
||||||
// .c -> .o (quick hack to fix the name on linux)
|
// .c -> .o (quick hack to fix the name on linux)
|
||||||
@@ -308,7 +312,7 @@ void compiler_compile(void)
|
|||||||
if (create_exe)
|
if (create_exe)
|
||||||
{
|
{
|
||||||
const char *output_name = active_target_name();
|
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);
|
platform_linker(output_name, obj_files, output_file_count);
|
||||||
compiler_link_time = bench_mark();
|
compiler_link_time = bench_mark();
|
||||||
@@ -327,8 +331,9 @@ void compiler_compile(void)
|
|||||||
|
|
||||||
if (active_target.run_after_compile)
|
if (active_target.run_after_compile)
|
||||||
{
|
{
|
||||||
|
DEBUG_LOG("Will run");
|
||||||
printf("Launching %s...\n", output_name);
|
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);
|
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] == '/')
|
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);
|
file_add_wildcard_files(&files, path, false, suffix_list, suffix_count);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (name[name_len - 2] != '*') goto INVALID_NAME;
|
if (name[name_len - 2] != '*') goto INVALID_NAME;
|
||||||
if (name_len == 2 || name[name_len - 3] == '/')
|
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);
|
file_add_wildcard_files(&files, path, true, suffix_list, suffix_count);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -490,8 +495,11 @@ void print_syntax(BuildOptions *options)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void resolve_libraries(void);
|
||||||
|
|
||||||
void compile()
|
void compile()
|
||||||
{
|
{
|
||||||
|
symtab_init(active_target.symtab_size);
|
||||||
active_target.sources = target_expand_source_names(active_target.source_dirs, c3_suffix_list, 3, true);
|
active_target.sources = target_expand_source_names(active_target.source_dirs, c3_suffix_list, 3, true);
|
||||||
if (active_target.csource_dirs)
|
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);
|
active_target.csources = target_expand_source_names(active_target.csource_dirs, c_suffix_list, 1, false);
|
||||||
}
|
}
|
||||||
global_context.sources = active_target.sources;
|
global_context.sources = active_target.sources;
|
||||||
symtab_init(active_target.symtab_size);
|
|
||||||
target_setup(&active_target);
|
target_setup(&active_target);
|
||||||
|
resolve_libraries();
|
||||||
|
|
||||||
setup_int_define("C_SHORT_SIZE", platform_target.width_c_short, type_long);
|
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);
|
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)
|
switch (active_target.arch_os_target)
|
||||||
{
|
{
|
||||||
case X64_WINDOWS:
|
case WINDOWS_X64:
|
||||||
case X86_WINDOWS:
|
case WINDOWS_X86:
|
||||||
case X64_WINDOWS_GNU:
|
case MINGW_X64:
|
||||||
return ".obj";
|
return ".obj";
|
||||||
default:
|
default:
|
||||||
return ".o";
|
return ".o";
|
||||||
@@ -600,69 +608,11 @@ Module *compiler_find_or_create_module(Path *module_name, const char **parameter
|
|||||||
return module;
|
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)
|
const char *scratch_buffer_interned(void)
|
||||||
{
|
{
|
||||||
TokenType type = TOKEN_INVALID_TOKEN;
|
TokenType type = TOKEN_INVALID_TOKEN;
|
||||||
return symtab_add(global_context.scratch_buffer, global_context.scratch_buffer_len,
|
return symtab_add(scratch_buffer.str, scratch_buffer.len,
|
||||||
fnv1a(global_context.scratch_buffer, global_context.scratch_buffer_len), &type);
|
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);
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -22,4 +22,5 @@ extern double compiler_sema_time;
|
|||||||
extern double compiler_ir_gen_time;
|
extern double compiler_ir_gen_time;
|
||||||
extern double compiler_codegen_time;
|
extern double compiler_codegen_time;
|
||||||
extern double compiler_link_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];
|
||||||
@@ -51,6 +51,7 @@ typedef unsigned ExprId;
|
|||||||
typedef unsigned DeclId;
|
typedef unsigned DeclId;
|
||||||
typedef unsigned TypeInfoId;
|
typedef unsigned TypeInfoId;
|
||||||
|
|
||||||
|
|
||||||
typedef struct Int128_
|
typedef struct Int128_
|
||||||
{
|
{
|
||||||
uint64_t high;
|
uint64_t high;
|
||||||
@@ -1435,9 +1436,7 @@ typedef struct
|
|||||||
bool in_test_mode : 1;
|
bool in_test_mode : 1;
|
||||||
unsigned errors_found;
|
unsigned errors_found;
|
||||||
unsigned warnings_found;
|
unsigned warnings_found;
|
||||||
char scratch_buffer[MAX_STRING_BUFFER];
|
|
||||||
Decl ***locals_list;
|
Decl ***locals_list;
|
||||||
uint32_t scratch_buffer_len;
|
|
||||||
HTable compiler_defines;
|
HTable compiler_defines;
|
||||||
Module std_module;
|
Module std_module;
|
||||||
DeclTable symbols;
|
DeclTable symbols;
|
||||||
@@ -1554,6 +1553,7 @@ typedef struct
|
|||||||
} NameResolve;
|
} NameResolve;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern GlobalContext global_context;
|
extern GlobalContext global_context;
|
||||||
extern BuildTarget active_target;
|
extern BuildTarget active_target;
|
||||||
extern Ast *poisoned_ast;
|
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);
|
DeclId decltable_get(DeclTable *table, const char *name);
|
||||||
void decltable_set(DeclTable *table, Decl *decl);
|
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);
|
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_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);
|
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);
|
void target_setup(BuildTarget *build_target);
|
||||||
int target_alloca_addr_space();
|
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);
|
void c_abi_func_create(FunctionPrototype *proto);
|
||||||
|
|
||||||
bool token_is_any_type(TokenType type);
|
bool token_is_any_type(TokenType type);
|
||||||
const char *token_type_to_string(TokenType type);
|
const char *token_type_to_string(TokenType type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
AlignSize type_abi_alignment(Type *type);
|
AlignSize type_abi_alignment(Type *type);
|
||||||
AlignSize type_alloca_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);
|
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_linker(const char *output_file, const char **files, unsigned file_count);
|
||||||
void platform_compiler(const char **files, unsigned file_count, const char* flags);
|
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 CAT(a,b) CAT2(a,b) // force expand
|
||||||
#define CAT2(a,b) a##b // actually concatenate
|
#define CAT2(a,b) a##b // actually concatenate
|
||||||
|
|||||||
@@ -66,9 +66,9 @@ static bool filename_to_module_in_buffer(const char *path)
|
|||||||
for (int i = last_slash + 1; i < last_dot; i++)
|
for (int i = last_slash + 1; i < last_dot; i++)
|
||||||
{
|
{
|
||||||
char c = path[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
|
else
|
||||||
{
|
{
|
||||||
@@ -89,9 +89,9 @@ bool context_set_module_from_filename(ParseContext *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenType type = TOKEN_IDENT;
|
TokenType type = TOKEN_IDENT;
|
||||||
const char *module_name = symtab_add(global_context.scratch_buffer,
|
const char *module_name = symtab_add(scratch_buffer.str,
|
||||||
global_context.scratch_buffer_len,
|
scratch_buffer.len,
|
||||||
fnv1a(global_context.scratch_buffer, (uint32_t) global_context.scratch_buffer_len),
|
fnv1a(scratch_buffer.str, (uint32_t) scratch_buffer.len),
|
||||||
&type);
|
&type);
|
||||||
|
|
||||||
if (type != TOKEN_IDENT)
|
if (type != TOKEN_IDENT)
|
||||||
@@ -103,14 +103,14 @@ bool context_set_module_from_filename(ParseContext *context)
|
|||||||
Path *path = CALLOCS(Path);
|
Path *path = CALLOCS(Path);
|
||||||
path->span = INVALID_SPAN;
|
path->span = INVALID_SPAN;
|
||||||
path->module = module_name;
|
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);
|
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)
|
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.
|
// 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.");
|
SEMA_ERROR(path, "A module name may not have any upper case characters.");
|
||||||
return false;
|
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);
|
DEBUG_LOG("SEMA: Add import of '%s'.", path->module);
|
||||||
|
|
||||||
|
if (!str_has_no_uppercase(path->module))
|
||||||
if (!is_all_lower(path->module))
|
|
||||||
{
|
{
|
||||||
SEMA_ERROR(path, "A module is not expected to have any upper case characters, please change it.");
|
SEMA_ERROR(path, "A module is not expected to have any upper case characters, please change it.");
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ static inline void decltable_resize(DeclTable *table)
|
|||||||
*dest = id;
|
*dest = id;
|
||||||
}
|
}
|
||||||
table->entries = new_data;
|
table->entries = new_data;
|
||||||
table->max_load = new_capacity * TABLE_MAX_LOAD;
|
table->max_load = (uint32_t)(new_capacity * TABLE_MAX_LOAD);
|
||||||
table->capacity = new_capacity;
|
table->capacity = new_capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,6 +87,6 @@ void decltable_init(DeclTable *table, uint32_t initial_size)
|
|||||||
DeclId *entries = CALLOC(initial_size * sizeof(DeclId));
|
DeclId *entries = CALLOC(initial_size * sizeof(DeclId));
|
||||||
table->count = 0;
|
table->count = 0;
|
||||||
table->capacity = initial_size;
|
table->capacity = initial_size;
|
||||||
table->max_load = initial_size * TABLE_MAX_LOAD;
|
table->max_load = (uint32_t)(initial_size * TABLE_MAX_LOAD);
|
||||||
table->entries = entries;
|
table->entries = entries;
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ static void print_error(SourceSpan location, const char *message, PrintType prin
|
|||||||
{
|
{
|
||||||
current += row_len + 1;
|
current += row_len + 1;
|
||||||
row_len = 0;
|
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)
|
if (row_len > max_lines_for_display)
|
||||||
{
|
{
|
||||||
eprintf(number_buffer_elided, row, max_lines_for_display - 1, current);
|
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)
|
static void vprint_error(SourceSpan location, const char *message, va_list args)
|
||||||
{
|
{
|
||||||
#define MAX_ERROR_LEN 4096
|
print_error(location, str_vprintf(message, args), PRINT_TYPE_ERROR);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -251,7 +243,7 @@ const char *span_to_string(SourceSpan span)
|
|||||||
}
|
}
|
||||||
assert(row == row_to_find);
|
assert(row == row_to_find);
|
||||||
const char *start = current + col - 1;
|
const char *start = current + col - 1;
|
||||||
return copy_string(start, length);
|
return str_copy(start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ Float float_from_string(const char *string, char **error)
|
|||||||
if (error) *error = err_float_out_of_range;
|
if (error) *error = err_float_out_of_range;
|
||||||
return (Float){ .type = TYPE_POISONED };
|
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 (d == 0 && end != expected_end)
|
||||||
{
|
{
|
||||||
if (error) *error = err_float_format_invalid;
|
if (error) *error = err_float_format_invalid;
|
||||||
@@ -200,7 +200,7 @@ Float float_from_hex(const char *string, char **error)
|
|||||||
char c;
|
char c;
|
||||||
scratch_buffer_clear();
|
scratch_buffer_clear();
|
||||||
scratch_buffer_append("0x");
|
scratch_buffer_append("0x");
|
||||||
while ((c = *(index++)) && (c == '_' || is_hex(c)))
|
while ((c = *(index++)) && (c == '_' || char_is_hex(c)))
|
||||||
{
|
{
|
||||||
if (c == '_') continue;
|
if (c == '_') continue;
|
||||||
scratch_buffer_append_char(c);
|
scratch_buffer_append_char(c);
|
||||||
@@ -208,7 +208,7 @@ Float float_from_hex(const char *string, char **error)
|
|||||||
if (c == '.')
|
if (c == '.')
|
||||||
{
|
{
|
||||||
scratch_buffer_append_char(c);
|
scratch_buffer_append_char(c);
|
||||||
while ((c = *(index++)) && (c == '_' || is_hex(c)))
|
while ((c = *(index++)) && (c == '_' || char_is_hex(c)))
|
||||||
{
|
{
|
||||||
if (c == '_') continue;
|
if (c == '_') continue;
|
||||||
scratch_buffer_append_char(c);
|
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;
|
if (error) *error = err_float_out_of_range;
|
||||||
return (Float){ .type = TYPE_POISONED };
|
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;
|
if (error) *error = err_float_format_invalid;
|
||||||
return (Float){ .type = TYPE_POISONED };
|
return (Float){ .type = TYPE_POISONED };
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ void header_gen(Module *module)
|
|||||||
{
|
{
|
||||||
TODO
|
TODO
|
||||||
CompilationUnit *unit = module->units[0];
|
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");
|
FILE *file = fopen(filename, "w");
|
||||||
OUTPUT("#include <stdint.h>\n");
|
OUTPUT("#include <stdint.h>\n");
|
||||||
OUTPUT("#ifndef __c3__\n");
|
OUTPUT("#ifndef __c3__\n");
|
||||||
|
|||||||
@@ -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)
|
static bool scan_number_suffix(Lexer *lexer, bool *is_float)
|
||||||
{
|
{
|
||||||
char c = peek(lexer);
|
char c = peek(lexer);
|
||||||
if (!is_alphanum_(c)) return true;
|
if (!char_is_alphanum_(c)) return true;
|
||||||
switch (c)
|
switch (c)
|
||||||
{
|
{
|
||||||
case 'u':
|
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);
|
return add_error_token_at_current(lexer, "Integer suffix '%c' is not valid for a floating point literal.", c);
|
||||||
}
|
}
|
||||||
next(lexer);
|
next(lexer);
|
||||||
while (is_number(c = peek(lexer))) next(lexer);
|
while (char_is_digit(c = peek(lexer))) next(lexer);
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
next(lexer);
|
next(lexer);
|
||||||
*is_float = true;
|
*is_float = true;
|
||||||
while (is_number(c = peek(lexer))) next(lexer);
|
while (char_is_digit(c = peek(lexer))) next(lexer);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (is_alphanum_(c))
|
if (char_is_alphanum_(c))
|
||||||
{
|
{
|
||||||
next(lexer);
|
next(lexer);
|
||||||
return add_error_token(lexer, "This doesn't seem to be a valid literal.");
|
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)
|
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).");
|
return add_error_token_at_current(lexer, "An expression starting with '0o' should be followed by octal numbers (0-7).");
|
||||||
}
|
}
|
||||||
next(lexer);
|
next(lexer);
|
||||||
while (is_oct_or_(peek(lexer))) next(lexer);
|
while (char_is_oct_or_(peek(lexer))) next(lexer);
|
||||||
if (is_number(peek(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).");
|
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)
|
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).");
|
return add_error_token_at_current(lexer, "An expression starting with '0b' should be followed by binary digits (0-1).");
|
||||||
}
|
}
|
||||||
next(lexer);
|
next(lexer);
|
||||||
while (is_binary_or_(peek(lexer))) next(lexer);
|
while (char_is_binary_or_(peek(lexer))) next(lexer);
|
||||||
if (is_number(peek((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).");
|
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);
|
next(lexer);
|
||||||
}
|
}
|
||||||
// Now we need at least one digit
|
// Now we need at least one digit
|
||||||
if (!is_digit(c))
|
if (!char_is_digit(c))
|
||||||
{
|
{
|
||||||
if (c == 0)
|
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);
|
return add_error_token(lexer, "Parsing the floating point exponent failed, because '%c' is not a number.", c);
|
||||||
}
|
}
|
||||||
// Walk through all of the digits.
|
// Walk through all of the digits.
|
||||||
while (is_digit(peek(lexer))) next(lexer);
|
while (char_is_digit(peek(lexer))) next(lexer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -497,12 +497,12 @@ static inline bool scan_exponent(Lexer *lexer)
|
|||||||
**/
|
**/
|
||||||
static inline bool scan_hex(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.");
|
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);
|
next(lexer);
|
||||||
while (is_hex_or_(peek(lexer))) next(lexer);
|
while (char_is_hex_or_(peek(lexer))) next(lexer);
|
||||||
bool is_float = false;
|
bool is_float = false;
|
||||||
if (peek(lexer) == '.' && peek_next(lexer) != '.')
|
if (peek(lexer) == '.' && peek_next(lexer) != '.')
|
||||||
{
|
{
|
||||||
@@ -510,8 +510,8 @@ static inline bool scan_hex(Lexer *lexer)
|
|||||||
next(lexer);
|
next(lexer);
|
||||||
char c = peek(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 (c == '_') return add_error_token_at_current(lexer, "'_' is not allowed directly after decimal point, try removing it.");
|
||||||
if (is_hex(c)) next(lexer);
|
if (char_is_hex(c)) next(lexer);
|
||||||
while (is_hex_or_(peek(lexer))) next(lexer);
|
while (char_is_hex_or_(peek(lexer))) next(lexer);
|
||||||
}
|
}
|
||||||
char c = peek(lexer);
|
char c = peek(lexer);
|
||||||
if (c == 'p' || c == 'P')
|
if (c == 'p' || c == 'P')
|
||||||
@@ -533,11 +533,11 @@ static inline bool scan_hex(Lexer *lexer)
|
|||||||
*/
|
*/
|
||||||
static inline bool scan_dec(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
|
// Walk through the digits, we don't need to worry about
|
||||||
// initial _ because we only call this if we have a digit initially.
|
// 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.
|
// Assume no float.
|
||||||
bool is_float = false;
|
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.");
|
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.
|
// Now walk until we see no more digits.
|
||||||
// This allows 123. as a floating point number.
|
// 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);
|
char c = peek(lexer);
|
||||||
// We might have an exponential. We allow 123e1 and 123.e1 as floating point, so
|
// 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++)
|
for (int j = 0; j < positions; j++)
|
||||||
{
|
{
|
||||||
hex <<= 4U;
|
hex <<= 4U;
|
||||||
int i = char_to_nibble(peek(lexer));
|
int i = char_hex_to_nibble(peek(lexer));
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
{
|
{
|
||||||
return -1;
|
return -1;
|
||||||
@@ -739,7 +739,7 @@ static inline bool scan_char(Lexer *lexer)
|
|||||||
{
|
{
|
||||||
assert(c == '\\');
|
assert(c == '\\');
|
||||||
c = peek(lexer);
|
c = peek(lexer);
|
||||||
escape = is_valid_escape(c);
|
escape = char_is_valid_escape(c);
|
||||||
if (escape == -1)
|
if (escape == -1)
|
||||||
{
|
{
|
||||||
lexer->lexing_start += 1;
|
lexer->lexing_start += 1;
|
||||||
@@ -826,15 +826,15 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
|
|||||||
{
|
{
|
||||||
int scanned;
|
int scanned;
|
||||||
uint64_t unicode_char;
|
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;
|
if (scanned_char < 0) return -1;
|
||||||
switch (scanned_char)
|
switch (scanned_char)
|
||||||
{
|
{
|
||||||
case 'x':
|
case 'x':
|
||||||
{
|
{
|
||||||
int h = char_to_nibble(src[1]);
|
int h = char_hex_to_nibble(src[1]);
|
||||||
if (h < 0) return -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;
|
if (l < 0) return -1;
|
||||||
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
|
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
|
||||||
scanned = 3;
|
scanned = 3;
|
||||||
@@ -842,13 +842,13 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
|
|||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
int x1 = char_to_nibble(src[1]);
|
int x1 = char_hex_to_nibble(src[1]);
|
||||||
if (x1 < 0) return -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;
|
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;
|
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;
|
if (x4 < 0) return -1;
|
||||||
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
|
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
|
||||||
scanned = 5;
|
scanned = 5;
|
||||||
@@ -856,21 +856,21 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
|
|||||||
}
|
}
|
||||||
case 'U':
|
case 'U':
|
||||||
{
|
{
|
||||||
int x1 = char_to_nibble(src[1]);
|
int x1 = char_hex_to_nibble(src[1]);
|
||||||
if (x1 < 0) return -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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
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;
|
if (x8 < 0) return -1;
|
||||||
unicode_char = ((unsigned) x1 << 28U) + ((unsigned) x2 << 24U) + ((unsigned) x3 << 20U) + ((unsigned) x4 << 16U) +
|
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;
|
((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);
|
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 (c == start_char) break;
|
||||||
if (is_hex(c))
|
if (char_is_hex(c))
|
||||||
{
|
{
|
||||||
next(lexer);
|
next(lexer);
|
||||||
len++;
|
len++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (is_whitespace(c))
|
if (char_is_whitespace(c))
|
||||||
{
|
{
|
||||||
next(lexer);
|
next(lexer);
|
||||||
continue;
|
continue;
|
||||||
@@ -1080,7 +1080,7 @@ static inline bool scan_base64(Lexer *lexer)
|
|||||||
}
|
}
|
||||||
next(lexer);
|
next(lexer);
|
||||||
if (c == start_char) break;
|
if (c == start_char) break;
|
||||||
if (is_base64(c))
|
if (char_is_base64(c))
|
||||||
{
|
{
|
||||||
if (end_len)
|
if (end_len)
|
||||||
{
|
{
|
||||||
@@ -1098,7 +1098,7 @@ static inline bool scan_base64(Lexer *lexer)
|
|||||||
end_len++;
|
end_len++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!is_whitespace(c))
|
if (!char_is_whitespace(c))
|
||||||
{
|
{
|
||||||
if (c < ' ' || c > 127)
|
if (c < ' ' || c > 127)
|
||||||
{
|
{
|
||||||
@@ -1297,7 +1297,7 @@ static bool lexer_scan_token_inner(Lexer *lexer)
|
|||||||
case '$':
|
case '$':
|
||||||
if (match(lexer, '$'))
|
if (match(lexer, '$'))
|
||||||
{
|
{
|
||||||
if (is_letter(peek(lexer)))
|
if (char_is_letter(peek(lexer)))
|
||||||
{
|
{
|
||||||
return return_token(lexer, TOKEN_BUILTIN, "$$");
|
return return_token(lexer, TOKEN_BUILTIN, "$$");
|
||||||
}
|
}
|
||||||
|
|||||||
190
src/compiler/libraries.c
Normal file
190
src/compiler/libraries.c
Normal 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]));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,12 +2,6 @@
|
|||||||
|
|
||||||
#include <llvm/Config/llvm-config.h> // for LLVM_VERSION_STRING
|
#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_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_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);
|
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 = "";
|
char *res = "";
|
||||||
for (unsigned i = 0; i < count; ++i)
|
for (unsigned i = 0; i < count; ++i)
|
||||||
{
|
{
|
||||||
res = strcat_arena(res, args[i]);
|
res = str_cat(res, args[i]);
|
||||||
}
|
}
|
||||||
return res;
|
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("-m");
|
||||||
add_arg("i386pep");
|
add_arg("i386pep");
|
||||||
add_arg("-Bdynamic");
|
add_arg("-Bdynamic");
|
||||||
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crt2.o" }, 2));
|
const char *root = getenv("MSYSTEM_PREFIX");
|
||||||
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crtbegin.o" }, 2));
|
const char *gcc_base = strformat("%s/lib/gcc/x86_64-w64-mingw32", root);
|
||||||
add_arg(join_strings((const char *[]){ "-L", root, "\\x86_64-w64-mingw32\\lib" }, 3));
|
if (!file_exists(gcc_base)) error_exit("Missing GCC");
|
||||||
add_arg(join_strings((const char *[]){ "-L", root, "\\lib" }, 3));
|
const char *name = file_first(gcc_base);
|
||||||
add_arg(join_strings((const char *[]){ "-L", root, "\\x86_64-w64-mingw32\\sys-root\\mingw\\lib" }, 3));
|
const char *gcc_path = strformat("%s/%s/", gcc_base, name);
|
||||||
add_arg(join_strings((const char *[]){ "-L", root, "\\lib\\clang\\", LLVM_VERSION_STRING, "\\lib\\windows" }, 5));
|
add_arg(strformat("-L%s/x86_64-w64-mingw32/lib", root));
|
||||||
add_files(args, files_to_link, file_count);
|
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("-lmingw32");
|
||||||
add_arg(join_strings((const char *[]){ root, "\\lib\\clang\\", LLVM_VERSION_STRING,
|
add_arg("-lgcc");
|
||||||
"\\lib\\windows\\libclang_rt.builtins-x86_64.a" }, 4));
|
add_arg("-lgcc_eh");
|
||||||
add_arg("-lunwind");
|
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("-lmoldname");
|
||||||
add_arg("-lmingwex");
|
add_arg("-lmingwex");
|
||||||
add_arg("-lmsvcrt");
|
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("-luser32");
|
||||||
add_arg("-lkernel32");
|
add_arg("-lkernel32");
|
||||||
add_arg("-lmingw32");
|
add_arg("-lmingw32");
|
||||||
add_arg(join_strings((const char *[]){ root, "\\lib\\clang\\", LLVM_VERSION_STRING,
|
add_arg2(lib, "\\crtend.o");
|
||||||
"\\lib\\windows\\libclang_rt.builtins-x86_64.a" }, 4));
|
}
|
||||||
add_arg("-lunwind");
|
*/
|
||||||
add_arg("-lmoldname");
|
#endif
|
||||||
add_arg("-lmingwex");
|
|
||||||
add_arg("-lmsvcrt");
|
static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
|
||||||
add_arg("-lkernel32");
|
{
|
||||||
add_arg(join_strings((const char *[]){ root, "\\x86_64-w64-mingw32\\lib\\crtend.o" }, 2));
|
if (linker_type == LINKER_CC) return;
|
||||||
#undef add_arg
|
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:
|
return "/usr/lib/x86_64-linux-gnu/";
|
||||||
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 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)
|
static void append_fpie_pic_options(RelocModel reloc, const char ***args_ref)
|
||||||
{
|
{
|
||||||
switch (reloc)
|
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)
|
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;
|
const char **args = NULL;
|
||||||
#ifdef _MSC_VER
|
LinkerType linker_type = linker_find_linker_type();
|
||||||
if (platform_target.os == OS_TYPE_WIN32)
|
linker_setup(&args, files_to_link, file_count, output_file, linker_type);
|
||||||
{
|
|
||||||
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
|
|
||||||
VECEACH(active_target.link_args, i)
|
VECEACH(active_target.link_args, i)
|
||||||
{
|
{
|
||||||
vec_add(args, active_target.link_args[i]);
|
vec_add(args, active_target.link_args[i]);
|
||||||
}
|
}
|
||||||
const char *error = NULL;
|
const char *error = NULL;
|
||||||
// This isn't used in most cases, but its contents should get freed after linking.
|
// 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;
|
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)
|
switch (platform_target.object_format)
|
||||||
{
|
{
|
||||||
case OBJ_FORMAT_COFF:
|
case OBJ_FORMAT_COFF:
|
||||||
if (platform_target.x64.is_mingw64)
|
success = llvm_link_coff(args, (int)vec_size(args), &error);
|
||||||
{
|
|
||||||
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
|
|
||||||
break;
|
break;
|
||||||
case OBJ_FORMAT_ELF:
|
case OBJ_FORMAT_ELF:
|
||||||
success = llvm_link_elf(args, (int)vec_size(args), &error);
|
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);
|
error_exit("Failed to create an executable: %s", error);
|
||||||
}
|
}
|
||||||
|
DEBUG_LOG("Linking complete.");
|
||||||
return true;
|
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)
|
void platform_linker(const char *output_file, const char **files, unsigned file_count)
|
||||||
{
|
{
|
||||||
|
DEBUG_LOG("Using cc linker.");
|
||||||
const char **parts = NULL;
|
const char **parts = NULL;
|
||||||
vec_add(parts, active_target.cc ? active_target.cc : "cc");
|
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);
|
append_fpie_pic_options(platform_target.reloc_model, &parts);
|
||||||
vec_add(parts, "-o");
|
linker_setup(&parts, files, file_count, output_file, LINKER_CC);
|
||||||
vec_add(parts, output_file);
|
|
||||||
for (unsigned i = 0; i < file_count; i++)
|
|
||||||
{
|
|
||||||
vec_add(parts, files[i]);
|
|
||||||
}
|
|
||||||
vec_add(parts, "-lm");
|
vec_add(parts, "-lm");
|
||||||
const char *output = concat_string_parts(parts);
|
const char *output = concat_string_parts(parts);
|
||||||
if (system(output) != 0)
|
if (system(output) != 0)
|
||||||
|
|||||||
@@ -472,9 +472,11 @@ static void gencontext_verify_ir(GenContext *context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void gencontext_emit_object_file(GenContext *context)
|
void gencontext_emit_object_file(GenContext *context)
|
||||||
{
|
{
|
||||||
char *err = "";
|
char *err = "";
|
||||||
|
DEBUG_LOG("Target: %s", platform_target.target_triple);
|
||||||
LLVMSetTarget(context->module, platform_target.target_triple);
|
LLVMSetTarget(context->module, platform_target.target_triple);
|
||||||
char *layout = LLVMCopyStringRepOfTargetData(context->target_data);
|
char *layout = LLVMCopyStringRepOfTargetData(context->target_data);
|
||||||
LLVMSetDataLayout(context->module, layout);
|
LLVMSetDataLayout(context->module, layout);
|
||||||
@@ -666,12 +668,33 @@ void llvm_codegen_setup()
|
|||||||
intrinsics_setup = true;
|
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)
|
void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
||||||
{
|
{
|
||||||
if (decl->module != c->code_module)
|
if (decl->module != c->code_module)
|
||||||
{
|
{
|
||||||
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
|
llvm_set_linkonce(c, value);
|
||||||
LLVMSetVisibility(value, LLVMDefaultVisibility);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Visibility visibility = decl->visibility;
|
Visibility visibility = decl->visibility;
|
||||||
@@ -680,8 +703,7 @@ void llvm_set_linkage(GenContext *c, Decl *decl, LLVMValueRef value)
|
|||||||
{
|
{
|
||||||
case VISIBLE_MODULE:
|
case VISIBLE_MODULE:
|
||||||
case VISIBLE_PUBLIC:
|
case VISIBLE_PUBLIC:
|
||||||
LLVMSetLinkage(value, LLVMLinkOnceODRLinkage);
|
llvm_set_linkonce(c, value);
|
||||||
LLVMSetVisibility(value, LLVMDefaultVisibility);
|
|
||||||
break;
|
break;
|
||||||
case VISIBLE_EXTERN:
|
case VISIBLE_EXTERN:
|
||||||
case VISIBLE_LOCAL:
|
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);
|
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);
|
LLVMSetGlobalConstant(global_name, 1);
|
||||||
LLVMSetInitializer(global_name, LLVMConstInt(llvm_get_type(c, type_char), 1, false));
|
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));
|
decl->type->backend_typeid = LLVMConstPointerCast(global_name, llvm_get_type(c, type_typeid));
|
||||||
|
|||||||
@@ -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_const_initialize_reference(GenContext *c, BEValue *ref, Expr *expr);
|
||||||
static inline void llvm_emit_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)
|
BEValue llvm_emit_assign_expr(GenContext *c, BEValue *ref, Expr *expr, LLVMValueRef failable)
|
||||||
{
|
{
|
||||||
assert(ref->kind == BE_ADDRESS || ref->kind == BE_ADDRESS_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);
|
llvm_value_set(be_value, val, expr->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void llvm_emit_post_unary_expr(GenContext *context, BEValue *be_value, Expr *expr)
|
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;
|
return;
|
||||||
|
|
||||||
PRIMITIVE:
|
PRIMITIVE:
|
||||||
LLVMSetLinkage(global_name, LLVMWeakAnyLinkage);
|
llvm_set_weak(c, global_name);
|
||||||
LLVMSetVisibility(global_name, LLVMDefaultVisibility);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void llvm_emit_typeid(GenContext *c, BEValue *be_value, Type *type)
|
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");
|
return LLVMConstRealOfString(type, f.f < 0 ? "-inf" : "inf");
|
||||||
}
|
}
|
||||||
scratch_buffer_clear();
|
scratch_buffer_clear();
|
||||||
#if LONG_DOUBLE
|
scratch_buffer_printf("%a", f.f);
|
||||||
global_context.scratch_buffer_len = sprintf(global_context.scratch_buffer, "%La", f.f);
|
return LLVMConstRealOfStringAndSize(type, scratch_buffer.str, scratch_buffer.len);
|
||||||
#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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr)
|
static inline void llvm_emit_const_initializer_list_expr(GenContext *c, BEValue *value, Expr *expr)
|
||||||
|
|||||||
@@ -457,11 +457,11 @@ void llvm_emit_function_body(GenContext *c, Decl *decl)
|
|||||||
LLVMTypeRef ptr_to_slot_type = LLVMPointerType(slot_type, 0);
|
LLVMTypeRef ptr_to_slot_type = LLVMPointerType(slot_type, 0);
|
||||||
if (!c->debug.last_ptr)
|
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);
|
LLVMSetThreadLocal(last_stack, true);
|
||||||
LLVMSetInitializer(last_stack, LLVMConstNull(ptr_to_slot_type));
|
LLVMSetInitializer(last_stack, LLVMConstNull(ptr_to_slot_type));
|
||||||
LLVMSetVisibility(last_stack, LLVMDefaultVisibility);
|
llvm_set_weak(c, last_stack);
|
||||||
LLVMSetLinkage(last_stack, LLVMWeakODRLinkage);
|
|
||||||
}
|
}
|
||||||
AlignSize alignment = llvm_abi_alignment(c, slot_type);
|
AlignSize alignment = llvm_abi_alignment(c, slot_type);
|
||||||
c->debug.stack_slot = llvm_emit_alloca(c, slot_type, alignment, ".$stackslot");
|
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)
|
switch (visibility)
|
||||||
{
|
{
|
||||||
case VISIBLE_EXTERN:
|
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);
|
LLVMSetVisibility(function, LLVMDefaultVisibility);
|
||||||
if (prototype->call_abi == CALL_X86_STD && platform_target.os == OS_TYPE_WIN32)
|
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;
|
break;
|
||||||
case VISIBLE_PUBLIC:
|
case VISIBLE_PUBLIC:
|
||||||
case VISIBLE_MODULE:
|
case VISIBLE_MODULE:
|
||||||
if (decl->func_decl.attr_weak) LLVMSetLinkage(function, LLVMWeakAnyLinkage);
|
if (decl->func_decl.attr_weak) llvm_set_weak(c, function);
|
||||||
LLVMSetVisibility(function, LLVMDefaultVisibility);
|
|
||||||
break;
|
break;
|
||||||
case VISIBLE_LOCAL:
|
case VISIBLE_LOCAL:
|
||||||
LLVMSetLinkage(function, decl->func_decl.attr_weak ? LLVMLinkerPrivateWeakLinkage : LLVMInternalLinkage);
|
LLVMSetLinkage(function, decl->func_decl.attr_weak ? LLVMLinkerPrivateWeakLinkage : LLVMInternalLinkage);
|
||||||
|
|||||||
@@ -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_body(GenContext *context, Decl *decl);
|
||||||
void llvm_emit_function_decl(GenContext *c, Decl *decl);
|
void llvm_emit_function_decl(GenContext *c, Decl *decl);
|
||||||
void llvm_emit_introspection_type_from_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);
|
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);
|
void llvm_emit_cast(GenContext *c, CastKind cast_kind, BEValue *value, Type *to_type, Type *from_type);
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ void gencontext_begin_module(GenContext *c)
|
|||||||
assert(!c->module && "Expected no module");
|
assert(!c->module && "Expected no module");
|
||||||
|
|
||||||
const char *result = module_create_object_file_name(c->code_module);
|
const char *result = module_create_object_file_name(c->code_module);
|
||||||
c->ir_filename = strformat("%s.ll", result);
|
c->ir_filename = str_printf("%s.ll", result);
|
||||||
c->object_filename = strformat("%s%s", result, get_object_extension());
|
c->object_filename = str_printf("%s%s", result, get_object_extension());
|
||||||
|
|
||||||
c->panicfn = global_context.panic_fn;
|
c->panicfn = global_context.panic_fn;
|
||||||
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
||||||
|
|||||||
@@ -1018,7 +1018,7 @@ static inline void llvm_emit_asm_stmt(GenContext *c, Ast *ast)
|
|||||||
LLVMValueRef asm_fn = LLVMGetInlineAsm(asm_fn_type,
|
LLVMValueRef asm_fn = LLVMGetInlineAsm(asm_fn_type,
|
||||||
(char *)ast->asm_stmt.body->const_expr.string.chars,
|
(char *)ast->asm_stmt.body->const_expr.string.chars,
|
||||||
ast->asm_stmt.body->const_expr.string.len,
|
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,
|
ast->asm_stmt.is_volatile,
|
||||||
true,
|
true,
|
||||||
LLVMInlineAsmDialectIntel
|
LLVMInlineAsmDialectIntel
|
||||||
|
|||||||
46
src/compiler/mac_support.c
Normal file
46
src/compiler/mac_support.c
Normal 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;
|
||||||
|
}
|
||||||
@@ -12,10 +12,10 @@ Decl *module_find_symbol(Module *module, const char *symbol)
|
|||||||
const char *module_create_object_file_name(Module *module)
|
const char *module_create_object_file_name(Module *module)
|
||||||
{
|
{
|
||||||
scratch_buffer_clear();
|
scratch_buffer_clear();
|
||||||
StringSlice slice = strtoslice(module->name->module);
|
StringSlice slice = slice_from_string(module->name->module);
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
StringSlice part = strnexttok(&slice, ':');
|
StringSlice part = slice_next_token(&slice, ':');
|
||||||
scratch_buffer_append_len(part.ptr, part.len);
|
scratch_buffer_append_len(part.ptr, part.len);
|
||||||
if (!slice.len) break;
|
if (!slice.len) break;
|
||||||
slice.ptr++;
|
slice.ptr++;
|
||||||
|
|||||||
@@ -224,15 +224,9 @@ const char *expr_const_to_error_string(const ExprConst *expr)
|
|||||||
case CONST_INTEGER:
|
case CONST_INTEGER:
|
||||||
return int_to_str(expr->ixx, 10);
|
return int_to_str(expr->ixx, 10);
|
||||||
case CONST_FLOAT:
|
case CONST_FLOAT:
|
||||||
#if LONG_DOUBLE
|
return str_printf("%g", expr->fxx.f);
|
||||||
asprintf(&buff, "%Lg", expr->fxx.f);
|
|
||||||
#else
|
|
||||||
asprintf(&buff, "%g", expr->fxx.f);
|
|
||||||
#endif
|
|
||||||
return buff;
|
|
||||||
case CONST_STRING:
|
case CONST_STRING:
|
||||||
asprintf(&buff, "\"%*.s\"", expr->string.len, expr->string.chars);
|
return str_printf("\"%*.s\"", expr->string.len, expr->string.chars);
|
||||||
return buff;
|
|
||||||
case CONST_BYTES:
|
case CONST_BYTES:
|
||||||
return "<binary data>";
|
return "<binary data>";
|
||||||
case CONST_ENUM:
|
case CONST_ENUM:
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ static Expr *parse_ct_stringify(ParseContext *c, Expr *left)
|
|||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
size_t len = end - start;
|
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 *expr = expr_new(EXPR_CONST, start_span);
|
||||||
expr->const_expr.const_kind = CONST_STRING;
|
expr->const_expr.const_kind = CONST_STRING;
|
||||||
expr->const_expr.string.chars = content;
|
expr->const_expr.string.chars = content;
|
||||||
@@ -1153,7 +1153,7 @@ static Expr *parse_integer(ParseContext *c, Expr *left)
|
|||||||
if (ch == '_') continue;
|
if (ch == '_') continue;
|
||||||
if (i.high > max) wrapped = true;
|
if (i.high > max) wrapped = true;
|
||||||
i = i128_shl64(i, 4);
|
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++;
|
hex_characters++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -1322,8 +1322,8 @@ static void parse_hex(char *result_pointer, const char *data, const char *end)
|
|||||||
{
|
{
|
||||||
int val;
|
int val;
|
||||||
int val2;
|
int val2;
|
||||||
while ((val = char_to_nibble(*(data++))) < 0) if (data == end) goto DONE;
|
while ((val = char_hex_to_nibble(*(data++))) < 0) if (data == end) goto DONE;
|
||||||
while ((val2 = char_to_nibble(*(data++))) < 0);
|
while ((val2 = char_hex_to_nibble(*(data++))) < 0);
|
||||||
|
|
||||||
*(data_current++) = (char)((val << 4) | val2);
|
*(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;
|
int scanned;
|
||||||
uint64_t unicode_char;
|
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;
|
if (scanned_char < 0) return -1;
|
||||||
switch (scanned_char)
|
switch (scanned_char)
|
||||||
{
|
{
|
||||||
case 'x':
|
case 'x':
|
||||||
{
|
{
|
||||||
int h = char_to_nibble(src[1]);
|
int h = char_hex_to_nibble(src[1]);
|
||||||
int l = char_to_nibble(src[2]);
|
int l = char_hex_to_nibble(src[2]);
|
||||||
if (h < 0 || l < 0) return -1;
|
if (h < 0 || l < 0) return -1;
|
||||||
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
|
unicode_char = ((unsigned) h << 4U) + (unsigned)l;
|
||||||
scanned = 3;
|
scanned = 3;
|
||||||
@@ -1511,10 +1511,10 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
|
|||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
int x1 = char_to_nibble(src[1]);
|
int x1 = char_hex_to_nibble(src[1]);
|
||||||
int x2 = char_to_nibble(src[2]);
|
int x2 = char_hex_to_nibble(src[2]);
|
||||||
int x3 = char_to_nibble(src[3]);
|
int x3 = char_hex_to_nibble(src[3]);
|
||||||
int x4 = char_to_nibble(src[4]);
|
int x4 = char_hex_to_nibble(src[4]);
|
||||||
if (x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0) return -1;
|
if (x1 < 0 || x2 < 0 || x3 < 0 || x4 < 0) return -1;
|
||||||
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
|
unicode_char = ((unsigned) x1 << 12U) + ((unsigned) x2 << 8U) + ((unsigned) x3 << 4U) + (unsigned)x4;
|
||||||
scanned = 5;
|
scanned = 5;
|
||||||
@@ -1522,14 +1522,14 @@ static int append_esc_string_token(char *restrict dest, const char *restrict src
|
|||||||
}
|
}
|
||||||
case 'U':
|
case 'U':
|
||||||
{
|
{
|
||||||
int x1 = char_to_nibble(src[1]);
|
int x1 = char_hex_to_nibble(src[1]);
|
||||||
int x2 = char_to_nibble(src[2]);
|
int x2 = char_hex_to_nibble(src[2]);
|
||||||
int x3 = char_to_nibble(src[3]);
|
int x3 = char_hex_to_nibble(src[3]);
|
||||||
int x4 = char_to_nibble(src[4]);
|
int x4 = char_hex_to_nibble(src[4]);
|
||||||
int x5 = char_to_nibble(src[5]);
|
int x5 = char_hex_to_nibble(src[5]);
|
||||||
int x6 = char_to_nibble(src[6]);
|
int x6 = char_hex_to_nibble(src[6]);
|
||||||
int x7 = char_to_nibble(src[7]);
|
int x7 = char_hex_to_nibble(src[7]);
|
||||||
int x8 = char_to_nibble(src[8]);
|
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;
|
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) +
|
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;
|
((unsigned) x5 << 12U) + ((unsigned) x6 << 8U) + ((unsigned) x7 << 4U) + (unsigned)x8;
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ static inline Path *parse_module_path(ParseContext *c)
|
|||||||
}
|
}
|
||||||
scratch_buffer_append("::");
|
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;
|
*had_error = false;
|
||||||
if (!tok_is(c, TOKEN_IDENT) || peek(c) != TOKEN_SCOPE) return NULL;
|
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;
|
uint32_t offset = 0;
|
||||||
|
|
||||||
Path *path = CALLOCS(Path);
|
Path *path = CALLOCS(Path);
|
||||||
|
|||||||
@@ -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 (!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));
|
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 false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -17,23 +17,23 @@ static bool sema_check_section(SemaContext *context, Decl *decl, Attr *attr)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
scratch_buffer_clear();
|
scratch_buffer_clear();
|
||||||
StringSlice slice = strtoslice(section_string);
|
StringSlice slice = slice_from_string(section_string);
|
||||||
StringSlice segment = strnexttok(&slice, ',');
|
StringSlice segment = slice_next_token(&slice, ',');
|
||||||
StringSlice section = strnexttok(&slice, ',');
|
StringSlice section = slice_next_token(&slice, ',');
|
||||||
StringSlice attrs = strnexttok(&slice, ',');
|
StringSlice attrs = slice_next_token(&slice, ',');
|
||||||
StringSlice stub_size_str = strnexttok(&slice, ',');
|
StringSlice stub_size_str = slice_next_token(&slice, ',');
|
||||||
|
|
||||||
if (slice.len)
|
if (slice.len)
|
||||||
{
|
{
|
||||||
SEMA_ERROR(attr->expr, "Too many parts to the Mach-o section description.");
|
SEMA_ERROR(attr->expr, "Too many parts to the Mach-o section description.");
|
||||||
}
|
}
|
||||||
slicetrim(&segment);
|
slice_trim(&segment);
|
||||||
if (segment.len == 0)
|
if (segment.len == 0)
|
||||||
{
|
{
|
||||||
SEMA_ERROR(attr->expr, "The segment is missing, did you type it correctly?");
|
SEMA_ERROR(attr->expr, "The segment is missing, did you type it correctly?");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
slicetrim(§ion);
|
slice_trim(§ion);
|
||||||
if (section.len == 0)
|
if (section.len == 0)
|
||||||
{
|
{
|
||||||
SEMA_ERROR(attr->expr, "Mach-o requires 'segment,section' as the format, did you type it correctly?");
|
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 *path = CALLOCS(Path);
|
||||||
path->module = path_string;
|
path->module = path_string;
|
||||||
path->span = module->name->span;
|
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);
|
instantiated_module = module_instantiate_generic(module, path, decl->define_decl.generic_params);
|
||||||
sema_analyze_stage(instantiated_module, c->unit->module->stage);
|
sema_analyze_stage(instantiated_module, c->unit->module->stage);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3083,11 +3083,7 @@ static inline bool sema_expr_analyse_type_access(SemaContext *context, Expr *exp
|
|||||||
{
|
{
|
||||||
expr->expr_kind = EXPR_CONST;
|
expr->expr_kind = EXPR_CONST;
|
||||||
expr->const_expr.const_kind = CONST_FLOAT;
|
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 };
|
expr->const_expr.fxx = (Float) { nan(""), canonical->type_kind };
|
||||||
#endif
|
|
||||||
expr->type = parent->type;
|
expr->type = parent->type;
|
||||||
expr->resolve_status = RESOLVE_DONE;
|
expr->resolve_status = RESOLVE_DONE;
|
||||||
return true;
|
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++)
|
for (ArraySize i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
char ch = string[i];
|
char ch = string[i];
|
||||||
if (!is_alphanum_(ch))
|
if (!char_is_alphanum_(ch))
|
||||||
{
|
{
|
||||||
if (ch == ':' && i > 0 && string[i + 1] == ':')
|
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++)
|
for (size_t i = 0; i < len; i++)
|
||||||
{
|
{
|
||||||
char c = string[i];
|
char c = string[i];
|
||||||
if (!is_alphanum_(c)) return false;
|
if (!char_is_alphanum_(c)) return false;
|
||||||
hash = FNV1a(c, hash);
|
hash = FNV1a(c, hash);
|
||||||
}
|
}
|
||||||
*ident_ref = symtab_find(string, len, hash, type_ref);
|
*ident_ref = symtab_find(string, len, hash, type_ref);
|
||||||
|
|||||||
@@ -47,12 +47,12 @@ File *source_file_load(const char *filename, bool *already_loaded)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t size;
|
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 = CALLOCS(File);
|
||||||
file->file_id = vec_size(global_context.loaded_sources);
|
file->file_id = vec_size(global_context.loaded_sources);
|
||||||
file->full_path = full_path;
|
file->full_path = full_path;
|
||||||
file->contents = source_text;
|
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);
|
vec_add(global_context.loaded_sources, file);
|
||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,9 +100,9 @@ void symtab_init(uint32_t capacity)
|
|||||||
{
|
{
|
||||||
const char* name = token_type_to_string((TokenType)i);
|
const char* name = token_type_to_string((TokenType)i);
|
||||||
// Skip non-keywords
|
// 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);
|
uint32_t len = (uint32_t)strlen(name);
|
||||||
TokenType type = (TokenType)i;
|
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->next = NULL;
|
||||||
node->index = fnv1hash;
|
node->index = fnv1hash;
|
||||||
node->type = *type;
|
node->type = *type;
|
||||||
return node->symbol = copy_string(data, len);
|
return node->symbol = str_copy(data, len);
|
||||||
}
|
}
|
||||||
SymtabEntry *bucket = first_bucket;
|
SymtabEntry *bucket = first_bucket;
|
||||||
do
|
do
|
||||||
@@ -257,7 +257,7 @@ const char *symtab_add(const char *data, uint32_t len, uint32_t fnv1hash, TokenT
|
|||||||
node->key_len = len;
|
node->key_len = len;
|
||||||
node->index = fnv1hash;
|
node->index = fnv1hash;
|
||||||
node->type = *type;
|
node->type = *type;
|
||||||
return node->symbol = copy_string(data, len);
|
return node->symbol = str_copy(data, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -174,8 +174,7 @@ void llvm_dump(void)
|
|||||||
}
|
}
|
||||||
LLVMTargetRef target;
|
LLVMTargetRef target;
|
||||||
char *error;
|
char *error;
|
||||||
char *triplet = NULL;
|
char *triplet = str_printf("%s-unknown-%s-unknown", archs[i], os[j]);
|
||||||
asprintf(&triplet, "%s-unknown-%s-unknown", archs[i], os[j]);
|
|
||||||
if (LLVMGetTargetFromTriple(triplet, &target, &error)) continue;
|
if (LLVMGetTargetFromTriple(triplet, &target, &error)) continue;
|
||||||
LLVMTargetMachineRef machine = NULL;
|
LLVMTargetMachineRef machine = NULL;
|
||||||
if (!(machine = LLVMCreateTargetMachine(target, triplet, "", "", 0, LLVMRelocDefault, LLVMCodeModelDefault))) {
|
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 (target->feature.soft_float == SOFT_FLOAT_YES) platform_target.x64.soft_float = true;
|
||||||
if (platform_target.environment_type == ENV_TYPE_GNU)
|
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)
|
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] = {
|
static char *arch_to_target_triple[ARCH_OS_TARGET_LAST + 1] = {
|
||||||
[X86_FREEBSD] = "i386-unknown-freebsd",
|
[FREEBSD_X86] = "i386-unknown-freebsd",
|
||||||
[X86_OPENBSD] = "i386-unknown-openbsd",
|
[OPENBSD_X86] = "i386-unknown-openbsd",
|
||||||
[X86_NETBSD] = "i386-unknown-netbsd",
|
[NETBSD_X86] = "i386-unknown-netbsd",
|
||||||
[X86_MCU] = "i386-pc-elfiamcu",
|
[MCU_X86] = "i386-pc-elfiamcu",
|
||||||
[X86_WINDOWS] = "i386-pc-win32",
|
[WINDOWS_X86] = "i386-pc-win32",
|
||||||
[X86_LINUX] = "i386-unknown-linux",
|
[LINUX_X86] = "i386-unknown-linux",
|
||||||
[X86_ELF] = "i386-unknown-elf",
|
[ELF_X86] = "i386-unknown-elf",
|
||||||
[X64_DARWIN] = "x86_64-apple-darwin-1",
|
[MACOS_X64] = "x86_64-apple-darwin",
|
||||||
[X64_LINUX] = "x86_64-pc-linux-gnu",
|
[LINUX_X64] = "x86_64-pc-linux-gnu",
|
||||||
[X64_WINDOWS] = "x86_64-pc-windows-msvc",
|
[WINDOWS_X64] = "x86_64-pc-windows-msvc",
|
||||||
[X64_WINDOWS_GNU] = "x86_64-w64-windows-gnu",
|
[MINGW_X64] = "x86_64-w64-windows-gnu",
|
||||||
[X64_NETBSD] = "x86_64-pc-netbsd",
|
[NETBSD_X64] = "x86_64-pc-netbsd",
|
||||||
[X64_FREEBSD] = "x86_64-pc-freebsd",
|
[FREEBSD_X64] = "x86_64-pc-freebsd",
|
||||||
[X64_OPENBSD] = "x86_64-pc-openbsd",
|
[OPENBSD_X64] = "x86_64-pc-openbsd",
|
||||||
[X64_ELF] = "x86_64-unknown-elf",
|
[ELF_X64] = "x86_64-unknown-elf",
|
||||||
[AARCH64_LINUX] = "aarch64-unknown-linux-gnu",
|
[LINUX_AARCH64] = "aarch64-unknown-linux-gnu",
|
||||||
[AARCH64_DARWIN] = "aarch64-apple-darwin",
|
[MACOS_AARCH64] = "aarch64-apple-darwin",
|
||||||
[AARCH64_ELF] = "aarch64-unknown-elf",
|
[ELF_AARCH64] = "aarch64-unknown-elf",
|
||||||
[RISCV32_LINUX] = "riscv32-unknown-linux",
|
[LINUX_RISCV32] = "riscv32-unknown-linux",
|
||||||
[RISCV32_ELF] = "riscv32-unknown-elf",
|
[ELF_RISCV32] = "riscv32-unknown-elf",
|
||||||
[RISCV64_LINUX] = "riscv64-unknown-linux",
|
[LINUX_RISCV64] = "riscv64-unknown-linux",
|
||||||
[RISCV64_ELF] = "riscv64-unknown-elf",
|
[ELF_RISCV64] = "riscv64-unknown-elf",
|
||||||
[WASM32] = "wasm32-unknown-unknown",
|
[WASM32] = "wasm32-unknown-unknown",
|
||||||
[WASM64] = "wasm64-unknown-unknown",
|
[WASM64] = "wasm64-unknown-unknown",
|
||||||
};
|
};
|
||||||
@@ -530,9 +572,10 @@ static bool arch_is_supported(ArchType arch)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static ArchType arch_from_llvm_string(StringSlice slice)
|
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("i386", ARCH_TYPE_X86)
|
||||||
STRCASE("i486", ARCH_TYPE_X86)
|
STRCASE("i486", ARCH_TYPE_X86)
|
||||||
STRCASE("i586", 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;
|
#define STRCASE(_str, _arch) if (slice_strcmp(env, _str)) return _arch;
|
||||||
STRCASE("gnu", ENV_TYPE_GNU)
|
STRCASE("gnu", ENV_TYPE_GNU)
|
||||||
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
|
STRCASE("gnuabin32", ENV_TYPE_GNUABIN32)
|
||||||
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
|
STRCASE("gnuabi64", ENV_TYPE_GNUABI64)
|
||||||
STRCASE("gnueabihf", ENV_TYPE_GNUEABIHF)
|
STRCASE("gnueabihf", ENV_TYPE_GNUEABIHF)
|
||||||
STRCASE("gnueabi", ENV_TYPE_GNUEABI)
|
STRCASE("gnueabi", ENV_TYPE_GNUEABI)
|
||||||
STRCASE("gnux32", ENV_TYPE_GNUX32)
|
STRCASE("gnux32", ENV_TYPE_GNUX32)
|
||||||
STRCASE("code16", ENV_TYPE_CODE16)
|
STRCASE("code16", ENV_TYPE_CODE16)
|
||||||
STRCASE("eabi", ENV_TYPE_EABI)
|
STRCASE("eabi", ENV_TYPE_EABI)
|
||||||
STRCASE("eabihf", ENV_TYPE_EABIHF)
|
STRCASE("eabihf", ENV_TYPE_EABIHF)
|
||||||
STRCASE("elfv1", ENV_TYPE_ELFV1)
|
STRCASE("elfv1", ENV_TYPE_ELFV1)
|
||||||
STRCASE("elfv2", ENV_TYPE_ELFV2)
|
STRCASE("elfv2", ENV_TYPE_ELFV2)
|
||||||
STRCASE("android", ENV_TYPE_ANDROID)
|
STRCASE("android", ENV_TYPE_ANDROID)
|
||||||
STRCASE("musl", ENV_TYPE_MUSL)
|
STRCASE("musl", ENV_TYPE_MUSL)
|
||||||
STRCASE("musleabi", ENV_TYPE_MUSLEABI)
|
STRCASE("musleabi", ENV_TYPE_MUSLEABI)
|
||||||
STRCASE("musleabihf", ENV_TYPE_MUSLEABIHF)
|
STRCASE("musleabihf", ENV_TYPE_MUSLEABIHF)
|
||||||
STRCASE("msvc", ENV_TYPE_MSVC)
|
STRCASE("msvc", ENV_TYPE_MSVC)
|
||||||
STRCASE("itanium", ENV_TYPE_ITANIUM)
|
STRCASE("itanium", ENV_TYPE_ITANIUM)
|
||||||
STRCASE("cygnus", ENV_TYPE_CYGNUS)
|
STRCASE("cygnus", ENV_TYPE_CYGNUS)
|
||||||
STRCASE("coreclr", ENV_TYPE_CORECLR)
|
STRCASE("coreclr", ENV_TYPE_CORECLR)
|
||||||
STRCASE("simulator", ENV_TYPE_SIMULATOR)
|
STRCASE("simulator", ENV_TYPE_SIMULATOR)
|
||||||
STRCASE("macabi", ENV_TYPE_MACABI)
|
STRCASE("macabi", ENV_TYPE_MACABI)
|
||||||
return ENV_TYPE_UNKNOWN;
|
return ENV_TYPE_UNKNOWN;
|
||||||
#undef STRCASE
|
#undef STRCASE
|
||||||
}
|
}
|
||||||
@@ -672,7 +715,7 @@ static OsType os_from_llvm_string(StringSlice os_string)
|
|||||||
break;
|
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("ananas", OS_TYPE_ANANAS)
|
||||||
STRCASE("cloudabi", OS_TYPE_CLOUD_ABI)
|
STRCASE("cloudabi", OS_TYPE_CLOUD_ABI)
|
||||||
STRCASE("darwin", OS_TYPE_MACOSX)
|
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)
|
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("apple", VENDOR_APPLE)
|
||||||
STRCASE("pc", VENDOR_PC)
|
STRCASE("pc", VENDOR_PC)
|
||||||
STRCASE("scei", VENDOR_SCEI)
|
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) target->arch_os_target = default_target;
|
||||||
|
|
||||||
if (target->arch_os_target == ARCH_OS_TARGET_DEFAULT)
|
platform_target.target_triple = arch_to_target_triple[target->arch_os_target];
|
||||||
{
|
|
||||||
platform_target.target_triple = LLVM_DEFAULT_TARGET_TRIPLE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
platform_target.target_triple = arch_to_target_triple[target->arch_os_target];
|
|
||||||
}
|
|
||||||
|
|
||||||
platform_target.alloca_address_space = 0;
|
platform_target.alloca_address_space = 0;
|
||||||
|
|
||||||
@@ -1299,18 +1335,18 @@ void target_setup(BuildTarget *target)
|
|||||||
|
|
||||||
LLVMTargetMachineRef machine = llvm_target_machine_create();
|
LLVMTargetMachineRef machine = llvm_target_machine_create();
|
||||||
char *target_triple = LLVMGetTargetMachineTriple(machine);
|
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);
|
LLVMDisposeMessage(target_triple);
|
||||||
LLVMDisposeTargetMachine(machine);
|
LLVMDisposeTargetMachine(machine);
|
||||||
|
|
||||||
StringSlice target_triple_string = strtoslice(platform_target.target_triple);
|
StringSlice target_triple_string = slice_from_string(platform_target.target_triple);
|
||||||
platform_target.arch = arch_from_llvm_string(strnexttok(&target_triple_string, '-'));
|
platform_target.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-'));
|
||||||
if (!arch_is_supported(platform_target.arch))
|
if (!arch_is_supported(platform_target.arch))
|
||||||
{
|
{
|
||||||
printf("WARNING! This architecture is not supported.\n");
|
printf("WARNING! This architecture is not supported.\n");
|
||||||
}
|
}
|
||||||
platform_target.vendor = vendor_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(strnexttok(&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.environment_type = environment_type_from_llvm_string(target_triple_string);
|
||||||
|
|
||||||
platform_target.float_abi = false;
|
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.width_pointer = arch_pointer_bit_width(platform_target.os, platform_target.arch);
|
||||||
platform_target.alloca_address_space = 0;
|
platform_target.alloca_address_space = 0;
|
||||||
platform_target.object_format = object_format_from_os(platform_target.os);
|
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.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);
|
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,
|
platform_target.environment_type,
|
||||||
active_target.type != TARGET_TYPE_EXECUTABLE);
|
active_target.type != TARGET_TYPE_EXECUTABLE);
|
||||||
platform_target.pic_required = arch_os_pic_default_forced(platform_target.arch, platform_target.os);
|
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
|
// Override PIC, but only if the platform does not require PIC
|
||||||
if (target->reloc_model != RELOC_DEFAULT
|
if (target->reloc_model != RELOC_DEFAULT
|
||||||
&& (target->reloc_model != RELOC_NONE || !platform_target.pic_required))
|
&& (target->reloc_model != RELOC_NONE || !platform_target.pic_required))
|
||||||
|
|||||||
@@ -266,6 +266,7 @@ typedef struct
|
|||||||
bool signed_c_char : 1;
|
bool signed_c_char : 1;
|
||||||
FloatABI float_abi : 3;
|
FloatABI float_abi : 3;
|
||||||
unsigned default_number_regs_x86 : 8;
|
unsigned default_number_regs_x86 : 8;
|
||||||
|
bool use_comdat : 1;
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
|||||||
@@ -91,14 +91,11 @@ Type *type_int_unsigned_by_bitsize(unsigned bytesize)
|
|||||||
|
|
||||||
const char *type_quoted_error_string(Type *type)
|
const char *type_quoted_error_string(Type *type)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
|
||||||
if (type->canonical != type)
|
if (type->canonical != type)
|
||||||
{
|
{
|
||||||
asprintf(&buffer, "'%s' (%s)", type_to_error_string(type), type_to_error_string(type->canonical));
|
return str_printf("'%s' (%s)", type_to_error_string(type), type_to_error_string(type->canonical));
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
asprintf(&buffer, "'%s'", type_to_error_string(type));
|
return str_printf("'%s'", type_to_error_string(type));
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void type_append_func_to_scratch(FunctionPrototype *prototype);
|
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)
|
const char *type_to_error_string(Type *type)
|
||||||
{
|
{
|
||||||
char *buffer = NULL;
|
|
||||||
switch (type->type_kind)
|
switch (type->type_kind)
|
||||||
{
|
{
|
||||||
case TYPE_POISONED:
|
case TYPE_POISONED:
|
||||||
@@ -231,11 +227,9 @@ const char *type_to_error_string(Type *type)
|
|||||||
case TYPE_FUNC:
|
case TYPE_FUNC:
|
||||||
scratch_buffer_clear();
|
scratch_buffer_clear();
|
||||||
type_append_func_to_scratch(type->func.prototype);
|
type_append_func_to_scratch(type->func.prototype);
|
||||||
asprintf(&buffer, "fn %s", scratch_buffer_to_string());
|
return str_printf("fn %s", scratch_buffer_to_string());
|
||||||
return buffer;
|
|
||||||
case TYPE_VECTOR:
|
case TYPE_VECTOR:
|
||||||
asprintf(&buffer, "%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
return str_printf("%s[<%llu>]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
||||||
return buffer;
|
|
||||||
case TYPE_TYPEINFO:
|
case TYPE_TYPEINFO:
|
||||||
return "typeinfo";
|
return "typeinfo";
|
||||||
case TYPE_TYPEID:
|
case TYPE_TYPEID:
|
||||||
@@ -247,22 +241,17 @@ const char *type_to_error_string(Type *type)
|
|||||||
{
|
{
|
||||||
return type_to_error_string(type->pointer);
|
return type_to_error_string(type->pointer);
|
||||||
}
|
}
|
||||||
asprintf(&buffer, "%s*", type_to_error_string(type->pointer));
|
return str_printf("%s*", type_to_error_string(type->pointer));
|
||||||
return buffer;
|
|
||||||
case TYPE_FAILABLE:
|
case TYPE_FAILABLE:
|
||||||
if (!type->failable) return "void!";
|
if (!type->failable) return "void!";
|
||||||
asprintf(&buffer, "%s!", type_to_error_string(type->failable));
|
return str_printf("%s!", type_to_error_string(type->failable));
|
||||||
return buffer;
|
|
||||||
case TYPE_ARRAY:
|
case TYPE_ARRAY:
|
||||||
asprintf(&buffer, "%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
return str_printf("%s[%llu]", type_to_error_string(type->array.base), (unsigned long long)type->array.len);
|
||||||
return buffer;
|
|
||||||
case TYPE_INFERRED_ARRAY:
|
case TYPE_INFERRED_ARRAY:
|
||||||
case TYPE_FLEXIBLE_ARRAY:
|
case TYPE_FLEXIBLE_ARRAY:
|
||||||
asprintf(&buffer, "%s[*]", type_to_error_string(type->array.base));
|
return str_printf("%s[*]", type_to_error_string(type->array.base));
|
||||||
return buffer;
|
|
||||||
case TYPE_SUBARRAY:
|
case TYPE_SUBARRAY:
|
||||||
asprintf(&buffer, "%s[]", type_to_error_string(type->array.base));
|
return str_printf("%s[]", type_to_error_string(type->array.base));
|
||||||
return buffer;
|
|
||||||
}
|
}
|
||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
@@ -555,7 +544,7 @@ static Type *type_generate_ptr(Type *ptr_type, bool canonical)
|
|||||||
Type *ptr = ptr_type->type_cache[PTR_OFFSET];
|
Type *ptr = ptr_type->type_cache[PTR_OFFSET];
|
||||||
if (ptr == NULL)
|
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->pointer = ptr_type;
|
||||||
ptr_type->type_cache[PTR_OFFSET] = ptr;
|
ptr_type->type_cache[PTR_OFFSET] = ptr;
|
||||||
if (ptr_type == ptr_type->canonical)
|
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];
|
Type *failable = failable_type->type_cache[FAILABLE_OFFSET];
|
||||||
if (failable == NULL)
|
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->pointer = failable_type;
|
||||||
failable_type->type_cache[FAILABLE_OFFSET] = failable;
|
failable_type->type_cache[FAILABLE_OFFSET] = failable;
|
||||||
if (failable_type == failable_type->canonical)
|
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];
|
Type *arr = arr_type->type_cache[SUB_ARRAY_OFFSET];
|
||||||
if (arr == NULL)
|
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->array.base = arr_type;
|
||||||
arr_type->type_cache[SUB_ARRAY_OFFSET] = arr;
|
arr_type->type_cache[SUB_ARRAY_OFFSET] = arr;
|
||||||
if (arr_type == arr_type->canonical)
|
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];
|
Type *arr = arr_type->type_cache[INFERRED_ARRAY_OFFSET];
|
||||||
if (arr == NULL)
|
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->array.base = arr_type;
|
||||||
arr_type->type_cache[INFERRED_ARRAY_OFFSET] = arr;
|
arr_type->type_cache[INFERRED_ARRAY_OFFSET] = arr;
|
||||||
if (arr_type == arr_type->canonical)
|
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];
|
Type *arr = arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET];
|
||||||
if (arr == NULL)
|
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.base = arr_type;
|
||||||
arr->array.len = 0;
|
arr->array.len = 0;
|
||||||
arr_type->type_cache[FLEXIBLE_ARRAY_OFFSET] = arr;
|
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;
|
Type *vec_arr;
|
||||||
if (vector)
|
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.base = element_type;
|
||||||
vec_arr->array.len = len;
|
vec_arr->array.len = len;
|
||||||
}
|
}
|
||||||
else
|
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.base = element_type;
|
||||||
vec_arr->array.len = len;
|
vec_arr->array.len = len;
|
||||||
}
|
}
|
||||||
@@ -995,7 +984,7 @@ void type_func_prototype_init(uint32_t capacity)
|
|||||||
assert(is_power_of_two(capacity) && capacity > 1);
|
assert(is_power_of_two(capacity) && capacity > 1);
|
||||||
map.entries = CALLOC(capacity * sizeof(FuncTypeEntry));
|
map.entries = CALLOC(capacity * sizeof(FuncTypeEntry));
|
||||||
map.capacity = capacity;
|
map.capacity = capacity;
|
||||||
map.max_load = TABLE_MAX_LOAD * capacity;
|
map.max_load = (uint32_t)(TABLE_MAX_LOAD * capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t hash_function(FunctionSignature *sig)
|
static uint32_t hash_function(FunctionSignature *sig)
|
||||||
@@ -1073,10 +1062,10 @@ static inline Type *func_create_new_func_proto(FunctionSignature *sig, CallABI a
|
|||||||
FuncTypeEntry *entries = map.entries;
|
FuncTypeEntry *entries = map.entries;
|
||||||
uint32_t old_capacity = map.capacity;
|
uint32_t old_capacity = map.capacity;
|
||||||
uint32_t new_capacity = map.capacity = old_capacity << 2;
|
uint32_t new_capacity = map.capacity = old_capacity << 2;
|
||||||
map.max_load = new_capacity * TABLE_MAX_LOAD;
|
map.max_load = (uint32_t)(new_capacity * TABLE_MAX_LOAD);
|
||||||
FuncTypeEntry *new_map = CALLOC(new_capacity * sizeof(FuncTypeEntry));
|
FuncTypeEntry *new_map = CALLOC(new_capacity * sizeof(FuncTypeEntry));
|
||||||
uint32_t new_mask = new_capacity - 1;
|
uint32_t new_mask = new_capacity - 1;
|
||||||
for (int i = 0; i < old_capacity; i++)
|
for (uint32_t i = 0; i < old_capacity; i++)
|
||||||
{
|
{
|
||||||
uint32_t key = entries[i].key;
|
uint32_t key = entries[i].key;
|
||||||
if (!key) continue;
|
if (!key) continue;
|
||||||
|
|||||||
40
src/compiler/windows_support.c
Normal file
40
src/compiler/windows_support.c
Normal 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
|
||||||
@@ -20,9 +20,7 @@
|
|||||||
#define MAX_IDENTIFIER_LENGTH 31
|
#define MAX_IDENTIFIER_LENGTH 31
|
||||||
#define MAX_SOURCE_LOCATION_LEN 255
|
#define MAX_SOURCE_LOCATION_LEN 255
|
||||||
#define PROJECT_JSON "project.c3p"
|
#define PROJECT_JSON "project.c3p"
|
||||||
#ifndef __unused
|
|
||||||
#define __unused
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( _WIN64 )
|
#if defined( _WIN32 ) || defined( __WIN32__ ) || defined( _WIN64 )
|
||||||
#define PLATFORM_WINDOWS 1
|
#define PLATFORM_WINDOWS 1
|
||||||
@@ -50,4 +48,13 @@
|
|||||||
#undef IS_GCC
|
#undef IS_GCC
|
||||||
#define IS_GCC 1
|
#define IS_GCC 1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef __printflike
|
||||||
|
#define __printflike(x, y)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __unused
|
||||||
|
#define __unused
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#define INLINE __attribute__((always_inline)) static inline
|
#define INLINE __attribute__((always_inline)) static inline
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
#define FALLTHROUGH ((void)0)
|
#define FALLTHROUGH ((void)0)
|
||||||
#define INLINE __forceinline static inline
|
#define INLINE static __forceinline
|
||||||
#define NORETURN __declspec(noreturn)
|
#define NORETURN __declspec(noreturn)
|
||||||
#define UNUSED
|
#define UNUSED
|
||||||
#else
|
#else
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
#define TODO FATAL_ERROR("TODO reached");
|
#define TODO FATAL_ERROR("TODO reached");
|
||||||
|
|
||||||
#define TEST_ASSERT(condition_, string_) while (!(condition_)) { FATAL_ERROR(string_); }
|
#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) \
|
#define EXPECT(_string, _value, _expected) \
|
||||||
do { long long __tempval1 = _value; long long __tempval2 = _expected; \
|
do { long long __tempval1 = _value; long long __tempval2 = _expected; \
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ static inline bool is_path_separator(char c)
|
|||||||
* @param directory_ptr the pointer to return the directory in.
|
* @param directory_ptr the pointer to return the directory in.
|
||||||
* @return false if only a directory could be found, true otherwise
|
* @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);
|
size_t len = strlen(path);
|
||||||
if (len == 0) return false;
|
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 == 1 && path[0] == '.') return false;
|
||||||
if (file_len == 2 && path[0] == '.' && path[1] == '.') return false;
|
if (file_len == 2 && path[0] == '.' && path[1] == '.') return false;
|
||||||
if (!file_len) 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 (!directory_ptr) return true;
|
||||||
if (file_len < len)
|
if (file_len < len)
|
||||||
{
|
{
|
||||||
size_t dir_len = len - file_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
|
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] == '/')
|
if (path[0] == '~' && path[1] == '/')
|
||||||
{
|
{
|
||||||
// Ignore leak.
|
|
||||||
char *ret = NULL;
|
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (!home || asprintf(&ret, "%s%s", home, &path[1]) == -1) return &path[2];
|
if (!home) return &path[2];
|
||||||
return ret;
|
return str_printf("%s%s", home, &path[1]);
|
||||||
}
|
}
|
||||||
return path;
|
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");
|
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)
|
static inline const char *lib_find(const char *exe_path, const char *rel_path)
|
||||||
{
|
{
|
||||||
struct stat info;
|
struct stat info;
|
||||||
char *lib_path = NULL;
|
scratch_buffer_clear();
|
||||||
asprintf(&lib_path, "%s%sstd", exe_path, rel_path);
|
scratch_buffer_printf("%s%sstd", exe_path, rel_path);
|
||||||
DEBUG_LOG("Checking %s", lib_path);
|
DEBUG_LOG("Checking %s", scratch_buffer_to_string());
|
||||||
int err = stat(lib_path, &info);
|
int err = stat(scratch_buffer_to_string(), &info);
|
||||||
|
|
||||||
// Not a dir or had error?
|
// Not a dir or had error?
|
||||||
if (err || !S_ISDIR(info.st_mode)) return NULL;
|
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...");
|
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;
|
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);
|
DEBUG_LOG("Library path found at %s", lib_path);
|
||||||
return lib_path;
|
return lib_path;
|
||||||
}
|
}
|
||||||
@@ -233,9 +230,9 @@ const char *find_lib_dir(void)
|
|||||||
return NULL;
|
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);
|
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;
|
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)
|
void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char **suffix_list, int suffix_count)
|
||||||
{
|
{
|
||||||
#ifdef _MSC_VER
|
#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))
|
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";
|
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
|
||||||
if (asprintf(&new_path, format, path, ent->d_name) == -1)
|
char *new_path = str_printf(format, path, ent->d_name);
|
||||||
{
|
|
||||||
error_exit("Failed to allocate path.");
|
|
||||||
}
|
|
||||||
bool is_directory;
|
bool is_directory;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (stat(new_path, &st))
|
if (stat(new_path, &st))
|
||||||
@@ -323,15 +358,57 @@ 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);
|
file_add_wildcard_files(files, new_path, recursive, suffix_list, suffix_count);
|
||||||
}
|
}
|
||||||
free(new_path);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char *format = path_ends_with_slash ? "%s%s" : "%s/%s";
|
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);
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
const char *execute_cmd(const char *cmd)
|
||||||
|
{
|
||||||
|
FATAL_ERROR("Not implemented");
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#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);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
|
|
||||||
char *realpath(const char *path, char *const resolved_path)
|
char *realpath(const char *path, char *const resolved_path)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#ifdef _MSC_VER
|
#include "lib.h"
|
||||||
|
|
||||||
#include "find_msvc.h"
|
#if PLATFORM_WINDOWS
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -25,10 +25,10 @@ typedef struct
|
|||||||
Find_Result find_visual_studio_and_windows_sdk();
|
Find_Result find_visual_studio_and_windows_sdk();
|
||||||
void free_resources(Find_Result* result);
|
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();
|
Find_Result paths = find_visual_studio_and_windows_sdk();
|
||||||
|
|
||||||
WindowsLinkPathsUTF8 out = { 0 };
|
WindowsSDK out = { 0 };
|
||||||
|
|
||||||
// note: WideCharToMultiByte doesn't seem to do null termination.
|
// note: WideCharToMultiByte doesn't seem to do null termination.
|
||||||
// I'm wary of manually adding a null terminator, so hopefully this is reliable.
|
// 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;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_windows_link_paths(WindowsLinkPathsUTF8* obj) {
|
void free_windows_link_paths(WindowsSDK* obj) {
|
||||||
free(obj->vs_library_path);
|
free(obj->vs_library_path);
|
||||||
free(obj->windows_sdk_ucrt_library_path);
|
free(obj->windows_sdk_ucrt_library_path);
|
||||||
free(obj->windows_sdk_um_library_path);
|
free(obj->windows_sdk_um_library_path);
|
||||||
@@ -95,6 +95,22 @@ void free_resources(Find_Result* result) {
|
|||||||
free(result->vs_library_path);
|
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
|
#undef INTERFACE
|
||||||
#define INTERFACE ISetupInstance
|
#define INTERFACE ISetupInstance
|
||||||
DECLARE_INTERFACE_(ISetupInstance, IUnknown)
|
DECLARE_INTERFACE_(ISetupInstance, IUnknown)
|
||||||
@@ -169,7 +185,7 @@ typedef struct {
|
|||||||
bool os_file_exists(wchar_t* name) {
|
bool os_file_exists(wchar_t* name) {
|
||||||
// @Robustness: What flags do we really want to check here?
|
// @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 == INVALID_FILE_ATTRIBUTES) return false;
|
||||||
if (attrib & FILE_ATTRIBUTE_DIRECTORY) 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
|
// If you don't like that, use a programming language that actually
|
||||||
// helps you with using custom allocators. Or just edit the code.
|
// helps you with using custom allocators. Or just edit the code.
|
||||||
|
|
||||||
auto len_a = wcslen(a);
|
size_t len_a = wcslen(a);
|
||||||
auto len_b = wcslen(b);
|
size_t len_b = wcslen(b);
|
||||||
|
|
||||||
auto len_c = 0;
|
size_t len_c = 0;
|
||||||
if (c) len_c = wcslen(c);
|
if (c) len_c = wcslen(c);
|
||||||
|
|
||||||
auto len_d = 0;
|
size_t len_d = 0;
|
||||||
if (d) len_d = wcslen(d);
|
if (d) len_d = wcslen(d);
|
||||||
|
|
||||||
wchar_t* result = (wchar_t*)malloc((len_a + len_b + len_c + len_d + 1) * 2);
|
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.
|
// If that's not the right terminology, hey, I never do registry stuff.
|
||||||
|
|
||||||
DWORD required_length;
|
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;
|
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.
|
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.
|
// Find the Windows 10 subdirectory with the highest version number.
|
||||||
|
|
||||||
int i0, i1, i2, i3;
|
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 (success < 4) return;
|
||||||
|
|
||||||
if (i0 < data->best_version[0]) 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.
|
// Find the Windows 8 subdirectory with the highest version number.
|
||||||
|
|
||||||
int i0, i1;
|
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 (success < 2) return;
|
||||||
|
|
||||||
if (i0 < data->best_version[0]) return;
|
if (i0 < data->best_version[0]) return;
|
||||||
|
|||||||
@@ -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);
|
|
||||||
@@ -165,12 +165,12 @@ static void json_parse_string(JsonParser *parser)
|
|||||||
char u2 = parser->current++[0];
|
char u2 = parser->current++[0];
|
||||||
char u3 = parser->current++[0];
|
char u3 = parser->current++[0];
|
||||||
char u4 = 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.");
|
json_error(parser, "Invalid hex in \\u escape sequence.");
|
||||||
return;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -64,4 +64,4 @@ typedef struct
|
|||||||
|
|
||||||
void json_init_string(JsonParser *parser, const char *str, JsonAllocator *allocator);
|
void json_init_string(JsonParser *parser, const char *str, JsonAllocator *allocator);
|
||||||
JSONObject *json_parse(JsonParser *parser);
|
JSONObject *json_parse(JsonParser *parser);
|
||||||
JSONObject *json_obj_get(JSONObject *obj, const char *key);
|
JSONObject *json_obj_get(JSONObject *obj, const char *key);
|
||||||
|
|||||||
716
src/utils/lib.h
716
src/utils/lib.h
@@ -11,14 +11,42 @@
|
|||||||
#include "direct.h"
|
#include "direct.h"
|
||||||
#endif
|
#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
|
#define COMPILER_SUCCESS_EXIT -1000
|
||||||
|
NORETURN void exit_compiler(int exit_value);
|
||||||
extern jmp_buf on_err_jump;
|
extern jmp_buf on_err_jump;
|
||||||
|
|
||||||
extern bool debug_log;
|
extern bool debug_log;
|
||||||
extern bool debug_stats;
|
extern bool debug_stats;
|
||||||
extern uintptr_t arena_zero;
|
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_
|
typedef struct Task_
|
||||||
{
|
{
|
||||||
@@ -28,15 +56,20 @@ typedef struct Task_
|
|||||||
|
|
||||||
typedef void *TaskQueueRef;
|
typedef void *TaskQueueRef;
|
||||||
|
|
||||||
const char *str_without_suffix(const char *name, const char *suffix);
|
bool file_namesplit(const char *path, char** filename_ptr, char** directory_ptr);
|
||||||
bool filenamesplit(const char *path, char** filename_ptr, char** directory_ptr);
|
const char* file_expand_path(const char* path);
|
||||||
const char* expand_path(const char* path);
|
|
||||||
const char* find_lib_dir(void);
|
const char* find_lib_dir(void);
|
||||||
char *read_file(const char *path, size_t *return_size);
|
bool file_is_dir(const char *file);
|
||||||
void path_get_dir_and_filename_from_full(const char *full_path, char **filename, char **dir_path);
|
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();
|
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);
|
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);
|
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 *cmalloc(size_t size);
|
||||||
void *ccalloc(size_t size, size_t elements);
|
void *ccalloc(size_t size, size_t elements);
|
||||||
void memory_init(void);
|
void memory_init(void);
|
||||||
@@ -46,7 +79,6 @@ void memory_release();
|
|||||||
#define idptr(id_) ((void*)(((uintptr_t)id_) * 16 + arena_zero))
|
#define idptr(id_) ((void*)(((uintptr_t)id_) * 16 + arena_zero))
|
||||||
void *calloc_arena(size_t mem);
|
void *calloc_arena(size_t mem);
|
||||||
char *calloc_string(size_t len);
|
char *calloc_string(size_t len);
|
||||||
char *copy_string(const char *start, size_t str_len);
|
|
||||||
#define malloc_string calloc_string
|
#define malloc_string calloc_string
|
||||||
#define malloc_arena calloc_arena
|
#define malloc_arena calloc_arena
|
||||||
void free_arena(void);
|
void free_arena(void);
|
||||||
@@ -57,6 +89,78 @@ void taskqueue_add(TaskQueueRef queue, Task *task);
|
|||||||
void taskqueue_destroy(TaskQueueRef queue);
|
void taskqueue_destroy(TaskQueueRef queue);
|
||||||
void taskqueue_wait_for_completion(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
|
#if MEM_PRINT
|
||||||
#define MALLOC(mem) (printf("Alloc at %s %zu\n", __FUNCTION__, (size_t)(mem)), malloc_arena(mem))
|
#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)))
|
#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))
|
#define CALLOCS(type) calloc_arena(sizeof(type))
|
||||||
#endif
|
#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_PRIME 0x01000193u
|
||||||
#define FNV1_SEED 0x811C9DC5u
|
#define FNV1_SEED 0x811C9DC5u
|
||||||
@@ -396,12 +209,6 @@ static inline VHeader_* vec_new_(size_t element_size, size_t capacity)
|
|||||||
return header;
|
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)
|
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;
|
VHeader_ *header = vec;
|
||||||
header[-1].size = new_size;
|
header[-1].size = new_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void vec_pop(void *vec)
|
static inline void vec_pop(void *vec)
|
||||||
{
|
{
|
||||||
assert(vec);
|
assert(vec);
|
||||||
@@ -416,6 +224,7 @@ static inline void vec_pop(void *vec)
|
|||||||
VHeader_ *header = vec;
|
VHeader_ *header = vec;
|
||||||
header[-1].size--;
|
header[-1].size--;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void* expand_(void *vec, size_t element_size)
|
static inline void* expand_(void *vec, size_t element_size)
|
||||||
{
|
{
|
||||||
VHeader_ *header;
|
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)
|
#define VECLAST(_vec) (vec_size(_vec) ? (_vec)[vec_size(_vec) - 1] : NULL)
|
||||||
#endif
|
#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
|
#if IS_GCC || IS_CLANG
|
||||||
|
|
||||||
#define MAX(_a, _b) ({ \
|
#define MAX(_a, _b) ({ \
|
||||||
@@ -545,11 +306,258 @@ void slicetrim(StringSlice *slice);
|
|||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#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);
|
char *realpath(const char *path, char *resolved_path);
|
||||||
|
|
||||||
#define mkdir(name, unused) _mkdir(name)
|
#define mkdir(name, unused) _mkdir(name)
|
||||||
|
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,13 +37,6 @@ void *calloc_string(size_t len)
|
|||||||
return vmem_alloc(&char_arena, 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.
|
// Simple bump allocator with buckets.
|
||||||
void *calloc_arena(size_t mem)
|
void *calloc_arena(size_t mem)
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "stdio.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++)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strformat(const char *var, ...)
|
bool str_has_no_uppercase(const char *string)
|
||||||
{
|
{
|
||||||
va_list list;
|
char c;
|
||||||
va_start(list, var);
|
while ((c = *(string++)) != '\0')
|
||||||
int len = vsnprintf(NULL, 0, var, list);
|
{
|
||||||
va_end(list);
|
if (char_is_upper(c)) return false;
|
||||||
if (len < 1) return "";
|
}
|
||||||
va_start(list, var);
|
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);
|
char *buffer = malloc_string((uint32_t)len + 1);
|
||||||
int new_len = vsnprintf(buffer, len + 1, var, list);
|
int new_len = vsnprintf(buffer, len + 1, var, list);
|
||||||
va_end(list);
|
|
||||||
assert(len == new_len);
|
assert(len == new_len);
|
||||||
(void)new_len;
|
(void)new_len;
|
||||||
return buffer;
|
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 name_len = strlen(name);
|
||||||
size_t suffix_len = strlen(suffix);
|
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++)
|
for (size_t i = 0; i < slice->len; i++)
|
||||||
{
|
{
|
||||||
@@ -65,7 +112,7 @@ StringSlice strnexttok(StringSlice *slice, char separator)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void slicetrim(StringSlice *slice)
|
void slice_trim(StringSlice *slice)
|
||||||
{
|
{
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < slice->len; i++)
|
for (i = 0; i < slice->len; i++)
|
||||||
@@ -81,9 +128,54 @@ void slicetrim(StringSlice *slice)
|
|||||||
slice->len = i;
|
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 a_len = (unsigned)strlen(a);
|
||||||
unsigned b_len = (unsigned)strlen(b);
|
unsigned b_len = (unsigned)strlen(b);
|
||||||
@@ -94,46 +186,86 @@ char *strcat_arena(const char *a, const char *b)
|
|||||||
return buffer;
|
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 += (uint32_t)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_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, format);
|
||||||
int res = vasprintf(strp, fmt, args);
|
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);
|
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;
|
if (scratch_buffer.len + 1 > MAX_STRING_BUFFER - 1)
|
||||||
va_copy(args_copy, args);
|
{
|
||||||
int res = vsprintf(NULL, fmt, args);
|
error_exit("Scratch buffer size (%d chars) exceeded", MAX_STRING_BUFFER - 1);
|
||||||
if (res < 0) goto END;
|
}
|
||||||
char *buf = ccalloc(res + 1, 1);
|
|
||||||
if (NULL == buf) goto END;
|
scratch_buffer.str[scratch_buffer.len++] = c;
|
||||||
sprintf(buf, fmt, args_copy); // this can't fail, right?
|
|
||||||
*strp = buf;
|
|
||||||
END:
|
|
||||||
va_end(args_copy);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int vasprintf(char** ret, const char* fmt, va_list args) {
|
char *scratch_buffer_to_string(void)
|
||||||
int length = _vsnprintf(NULL, 0, fmt, args);
|
{
|
||||||
if (length < 0) { // check if _vsnprintf failed
|
scratch_buffer.str[scratch_buffer.len] = '\0';
|
||||||
return -1;
|
return scratch_buffer.str;
|
||||||
}
|
}
|
||||||
*ret = cmalloc(length + 1);
|
|
||||||
if (!*ret) { // check if malloc failed
|
char *scratch_buffer_copy(void)
|
||||||
return -1;
|
{
|
||||||
}
|
return str_copy(scratch_buffer.str, scratch_buffer.len);
|
||||||
// Write String
|
|
||||||
_vsnprintf(*ret, length + 1, fmt, args);
|
|
||||||
(*ret)[length] = '\0'; // make sure there is a null terminator
|
|
||||||
return length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
#define COMPILER_VERSION "0.1.1"
|
#define COMPILER_VERSION "0.1.2"
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: aarch64-darwin
|
// #target: macos-aarch64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct Large {
|
struct Large {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: aarch64-darwin
|
// #target: macos-aarch64
|
||||||
module test;
|
module test;
|
||||||
define Int8x16 = ichar[<16>];
|
define Int8x16 = ichar[<16>];
|
||||||
define Float32x3 = float[<3>];
|
define Float32x3 = float[<3>];
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
// #opt: --x86vec=avx
|
// #opt: --x86vec=avx
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
// #opt: --x86vec=avx512
|
// #opt: --x86vec=avx512
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
// #opt: --x86vec=sse
|
// #opt: --x86vec=sse
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
fn char f0() {
|
fn char f0() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct St12
|
struct St12
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
struct Test
|
struct Test
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: aarch64-linux
|
// #target: linux-aarch64
|
||||||
module literal_load;
|
module literal_load;
|
||||||
|
|
||||||
struct Test
|
struct Test
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-mingw
|
// #target: mingw-x64
|
||||||
module literal_load;
|
module literal_load;
|
||||||
|
|
||||||
struct Test
|
struct Test
|
||||||
|
|||||||
@@ -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 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?
|
int bar @section("foo, "); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly?
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: aarch64-linux
|
// #target: linux-aarch64
|
||||||
|
|
||||||
module pass_large;
|
module pass_large;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-mingw
|
// #target: mingw-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
extern fn void printf(char*, ...);
|
extern fn void printf(char*, ...);
|
||||||
@@ -21,12 +21,12 @@ fn int main()
|
|||||||
|
|
||||||
%Foo = type { [2 x float] }
|
%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
|
declare void @printf(i8*, ...) #0
|
||||||
|
|
||||||
; Function Attrs: nounwind
|
|
||||||
define x86_regcallcc void @test.test(float %0, float %1) #0 {
|
define x86_regcallcc void @test.test(float %0, float %1) #0 {
|
||||||
entry:
|
entry:
|
||||||
%x = alloca %Foo, align 4
|
%x = alloca %Foo, align 4
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: riscv64-linux
|
// #target: linux-riscv64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct Large {
|
struct Large {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
struct Foo
|
struct Foo
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
struct Abc {
|
struct Abc {
|
||||||
long a;
|
long a;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module unionx64;
|
module unionx64;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: aarch64-linux
|
// #target: linux-aarch64
|
||||||
module abi;
|
module abi;
|
||||||
|
|
||||||
struct Vector2 {
|
struct Vector2 {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module abi;
|
module abi;
|
||||||
|
|
||||||
struct Vector2 {
|
struct Vector2 {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
extern fn void test1_f(void *);
|
extern fn void test1_f(void *);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module array_casts;
|
module array_casts;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module array_literal;
|
module array_literal;
|
||||||
|
|
||||||
fn double test(uint x)
|
fn double test(uint x)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct Foo
|
struct Foo
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct Connection
|
struct Connection
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-windows
|
// #target: windows-x64
|
||||||
|
|
||||||
fn int foo()
|
fn int foo()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
fn int foo(double b)
|
fn int foo(double b)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
struct Foo { int x, y; }
|
struct Foo { int x, y; }
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
fn int strcmp(char *s1, char *s2);
|
fn int strcmp(char *s1, char *s2);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
extern fn int printf(char *, ...);
|
extern fn int printf(char *, ...);
|
||||||
extern fn int foo();
|
extern fn int foo();
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
char[8192] stack;
|
char[8192] stack;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module foo;
|
module foo;
|
||||||
|
|
||||||
int x1 = 2 ^ 4;
|
int x1 = 2 ^ 4;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
extern fn void printf(char*, ...);
|
extern fn void printf(char*, ...);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
extern fn void printf(char*, ...);
|
extern fn void printf(char*, ...);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// #target: x64-darwin
|
// #target: macos-x64
|
||||||
|
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user