mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
MSVC compatibility
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -60,3 +60,8 @@ dkms.conf
|
|||||||
/resources/y.tab.c
|
/resources/y.tab.c
|
||||||
/resources/y.tab.h
|
/resources/y.tab.h
|
||||||
/bin/
|
/bin/
|
||||||
|
|
||||||
|
#visual studio files
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
out/
|
||||||
@@ -53,18 +53,21 @@ llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})
|
|||||||
|
|
||||||
file(COPY ${CMAKE_SOURCE_DIR}/resources/lib DESTINATION ${CMAKE_BINARY_DIR})
|
file(COPY ${CMAKE_SOURCE_DIR}/resources/lib DESTINATION ${CMAKE_BINARY_DIR})
|
||||||
|
|
||||||
find_library(LLD_COFF NAMES lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS})
|
# These don't seem to be reliable on windows.
|
||||||
find_library(LLD_COMMON NAMES lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
|
if(UNIX)
|
||||||
find_library(LLD_CORE NAMES lldCore.a liblldCore.a PATHS ${LLVM_LIBRARY_DIRS})
|
message(STATUS "using find_library")
|
||||||
find_library(LLD_WASM NAMES lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_COFF NAMES lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_MINGW NAMES lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_COMMON NAMES lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_ELF NAMES lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_CORE NAMES lldCore.a liblldCore.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_DRIVER NAMES lldDriver.a liblldDriver.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_WASM NAMES lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_READER_WRITER NAMES lldReaderWriter.a liblldReaderWriter.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_MINGW NAMES lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_MACHO NAMES lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_ELF NAMES lldELF.a liblldELF.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
find_library(LLD_YAML NAMES lldYAML.a liblldYAML.a PATHS ${LLVM_LIBRARY_DIRS})
|
find_library(LLD_DRIVER NAMES 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_MACHO NAMES lldMachO.a liblldMachO.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
|
find_library(LLD_YAML NAMES lldYAML.a liblldYAML.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||||
|
|
||||||
set(lld_libs
|
set(lld_libs
|
||||||
${LLD_COFF}
|
${LLD_COFF}
|
||||||
${LLD_COMMON}
|
${LLD_COMMON}
|
||||||
${LLD_WASM}
|
${LLD_WASM}
|
||||||
@@ -76,6 +79,8 @@ set(lld_libs
|
|||||||
${LLD_YAML}
|
${LLD_YAML}
|
||||||
${LLD_CORE}
|
${LLD_CORE}
|
||||||
)
|
)
|
||||||
|
message(STATUS "linking to llvm libs ${llvm_libs} ${lld_libs}")
|
||||||
|
endif()
|
||||||
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
|
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
|
||||||
|
|
||||||
add_executable(c3c
|
add_executable(c3c
|
||||||
@@ -107,6 +112,7 @@ add_executable(c3c
|
|||||||
src/compiler/module.c
|
src/compiler/module.c
|
||||||
src/compiler/llvm_codegen.c
|
src/compiler/llvm_codegen.c
|
||||||
src/utils/stringutils.c
|
src/utils/stringutils.c
|
||||||
|
src/utils/find_msvc.c
|
||||||
src/compiler/dwarf.h
|
src/compiler/dwarf.h
|
||||||
src/compiler/copying.c
|
src/compiler/copying.c
|
||||||
src/compiler/llvm_codegen_stmt.c
|
src/compiler/llvm_codegen_stmt.c
|
||||||
@@ -145,9 +151,11 @@ add_executable(c3c
|
|||||||
src/compiler/llvm_codegen_c_abi_riscv.c
|
src/compiler/llvm_codegen_c_abi_riscv.c
|
||||||
src/compiler/llvm_codegen_c_abi_wasm.c)
|
src/compiler/llvm_codegen_c_abi_wasm.c)
|
||||||
|
|
||||||
target_compile_options(c3c PRIVATE -Wall -Werror -Wno-unknown-pragmas -Wno-unused-result
|
if(NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
||||||
-Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)
|
message(STATUS "using gcc/clang warning switches")
|
||||||
|
target_compile_options(c3c PRIVATE -Wall -Werror -Wno-unknown-pragmas -Wno-unused-result
|
||||||
|
-Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(c3c PRIVATE
|
target_include_directories(c3c PRIVATE
|
||||||
"${CMAKE_SOURCE_DIR}/src/")
|
"${CMAKE_SOURCE_DIR}/src/")
|
||||||
@@ -158,9 +166,18 @@ target_include_directories(c3c_wrappers PRIVATE
|
|||||||
|
|
||||||
message(STATUS "Found LLD ${lld_libs}")
|
message(STATUS "Found LLD ${lld_libs}")
|
||||||
|
|
||||||
target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs})
|
if(UNIX)
|
||||||
#target_link_libraries(c3c m ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML)
|
message(STATUS "adding unix link params")
|
||||||
target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${lld_libs})
|
target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs})
|
||||||
|
target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${lld_libs})
|
||||||
|
else()
|
||||||
|
# todo: maybe get this from llvm-config somehow? it should be in LLVM_DIR\..\..\..\bin I think.
|
||||||
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -LIBPATH:C:\\llvm\\llvm\\build\\Release\\lib") # needed for lldCommon.lib
|
||||||
|
#set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -LIBPATH:${LLVM_LIBPATH}") # This doesn't seem to work for some reason
|
||||||
|
message(STATUS "${LLVM_LIBPATH}")
|
||||||
|
target_link_libraries(c3c debug ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML)
|
||||||
|
target_link_libraries(c3c optimized ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
if (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILE_ID STREQUAL "GNU")
|
if (CMAKE_C_COMPILER_ID STREQUAL "Clang" OR CMAKE_C_COMPILE_ID STREQUAL "GNU")
|
||||||
|
|||||||
15
CMakeSettings.json
Normal file
15
CMakeSettings.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "build",
|
||||||
|
"generator": "Ninja",
|
||||||
|
"configurationType": "Release",
|
||||||
|
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeCommandArgs": "-DLLVM_DIR=C:\\llvm\\llvm\\build\\lib\\cmake\\llvm -DCMAKE_CXX_FLAGS:STRING=\"${CMAKE_CXX_FLAGS} /J\"",
|
||||||
|
"buildCommandArgs": "-v",
|
||||||
|
"ctestCommandArgs": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -6,7 +6,9 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <utils/lib.h>
|
#include <utils/lib.h>
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
// Copyright (c) 2019 Christoffer Lerno. All rights reserved.
|
||||||
// Use of this source code is governed by a LGPLv3.0
|
// Use of this source code is governed by a LGPLv3.0
|
||||||
// a copy of which can be found in the LICENSE file.
|
// a copy of which can be found in the LICENSE file.
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#else
|
||||||
|
#include "utils/dirent.h"
|
||||||
|
#endif
|
||||||
#include "build_internal.h"
|
#include "build_internal.h"
|
||||||
#include "build_options.h"
|
#include "build_options.h"
|
||||||
|
|
||||||
@@ -93,6 +96,16 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
|||||||
{
|
{
|
||||||
target->arch_os_target = options->arch_os_target_override;
|
target->arch_os_target = options->arch_os_target_override;
|
||||||
}
|
}
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#define _MSC_VER 0
|
||||||
|
#endif
|
||||||
|
else if (_MSC_VER)
|
||||||
|
{
|
||||||
|
// The current handling of ARCH_OS_TARGET_DEFAULT works on unix, but not on windows.
|
||||||
|
// to deal with this, simply default to x64-windows (unless using mingw).
|
||||||
|
// ARCH_OS_TARGET_DEFAULT could be handled in a more cross-platform manner later on.
|
||||||
|
target->arch_os_target = X64_WINDOWS;
|
||||||
|
}
|
||||||
if (options->pie != PIE_DEFAULT) target->pie = options->pie;
|
if (options->pie != PIE_DEFAULT) target->pie = options->pie;
|
||||||
if (options->pic != PIC_DEFAULT) target->pic = options->pic;
|
if (options->pic != PIC_DEFAULT) target->pic = options->pic;
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include "project_creation.h"
|
#include "project_creation.h"
|
||||||
#include "build_options.h"
|
#include "build_options.h"
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
|
|
||||||
#include "compiler_internal.h"
|
#include "compiler_internal.h"
|
||||||
#include "parser_internal.h"
|
#include "parser_internal.h"
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MAX_OUTPUT_FILES 1000000
|
#define MAX_OUTPUT_FILES 1000000
|
||||||
#define MAX_MODULES 100000
|
#define MAX_MODULES 100000
|
||||||
@@ -483,7 +485,7 @@ static void target_expand_source_names(BuildTarget *target)
|
|||||||
|
|
||||||
void compile_target(BuildOptions *options)
|
void compile_target(BuildOptions *options)
|
||||||
{
|
{
|
||||||
init_default_build_target(&active_target, options, "a.out");
|
init_default_build_target(&active_target, options, DEFAULT_EXE);
|
||||||
compile();
|
compile();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,13 @@ typedef int32_t ScopeId;
|
|||||||
#define DEFAULT_EXE "a.out"
|
#define DEFAULT_EXE "a.out"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
#define DEFAULT_OBJ_FILE_EXT ".obj"
|
||||||
|
#else
|
||||||
|
#define DEFAULT_OBJ_FILE_EXT ".o"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef uint32_t SourceLoc;
|
typedef uint32_t SourceLoc;
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@@ -554,9 +561,9 @@ typedef struct Decl_
|
|||||||
SourceSpan span;
|
SourceSpan span;
|
||||||
const char *external_name;
|
const char *external_name;
|
||||||
Ast *docs;
|
Ast *docs;
|
||||||
DeclKind decl_kind : 6;
|
DeclKind decl_kind : 7;
|
||||||
Visibility visibility : 2;
|
Visibility visibility : 3;
|
||||||
ResolveStatus resolve_status : 2;
|
ResolveStatus resolve_status : 3;
|
||||||
bool is_packed : 1;
|
bool is_packed : 1;
|
||||||
bool is_opaque : 1;
|
bool is_opaque : 1;
|
||||||
bool needs_additional_pad : 1;
|
bool needs_additional_pad : 1;
|
||||||
|
|||||||
@@ -295,7 +295,7 @@ typedef enum
|
|||||||
TYPE_INFO_POINTER,
|
TYPE_INFO_POINTER,
|
||||||
} TypeInfoKind;
|
} TypeInfoKind;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
TOKEN_INVALID_TOKEN = 0,
|
TOKEN_INVALID_TOKEN = 0,
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
|
|
||||||
#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);
|
||||||
@@ -64,8 +68,19 @@ static void prepare_msys2_linker_flags(const char ***args, const char **files_to
|
|||||||
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)
|
||||||
{
|
{
|
||||||
const char **args = NULL;
|
const char **args = NULL;
|
||||||
vec_add(args, "-o");
|
#ifdef _MSC_VER
|
||||||
vec_add(args, output_file);
|
if (platform_target.os == OS_TYPE_WIN32)
|
||||||
|
{
|
||||||
|
vec_add(args, join_strings((const char* []) {"/out:", output_file}, 2));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
vec_add(args, "-o");
|
||||||
|
vec_add(args, output_file);
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
}
|
||||||
|
#endif
|
||||||
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]);
|
||||||
@@ -78,16 +93,43 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign
|
|||||||
// TODO: properly detect if llvm-lld is available
|
// TODO: properly detect if llvm-lld is available
|
||||||
// TODO: check if running inside MSYS2, it could be done via getting MSYSTEM environment variable
|
// 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
|
// https://stackoverflow.com/questions/65527286/how-to-check-if-my-program-is-running-on-mingwor-msys-shell-or-on-cmd
|
||||||
if (!platform_target.x64.is_mingw64) return false;
|
if (NULL == getenv("MSYSTEM"))
|
||||||
if (NULL == getenv("MSYSTEM")) return false;
|
|
||||||
if (!strcmp(getenv("MSYSTEM"), "CLANG64") || !strcmp(getenv("MSYSTEM"), "MINGW64"))
|
|
||||||
{
|
{
|
||||||
prepare_msys2_linker_flags(&args, files_to_link, file_count);
|
// "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
|
||||||
|
PathPair msvc_paths = get_latest_available_vs_path();
|
||||||
|
PathPair windows_kit_paths = find_winkit_path();
|
||||||
|
vec_add(args, join_strings((const char* []) { "-libpath:C:", msvc_paths.first }, 2));
|
||||||
|
vec_add(args, join_strings((const char* []) { "-libpath:C:", msvc_paths.second }, 2));
|
||||||
|
vec_add(args, join_strings((const char* []) { "-libpath:C:", windows_kit_paths.first }, 2));
|
||||||
|
vec_add(args, join_strings((const char* []) { "-libpath:C:", windows_kit_paths.second }, 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
|
else
|
||||||
{
|
{
|
||||||
return false;
|
if (!strcmp(getenv("MSYSTEM"), "CLANG64") || !strcmp(getenv("MSYSTEM"), "MINGW64"))
|
||||||
}
|
{
|
||||||
|
prepare_msys2_linker_flags(&args, files_to_link, file_count);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case OS_TYPE_MACOSX:
|
case OS_TYPE_MACOSX:
|
||||||
add_files(&args, files_to_link, file_count);
|
add_files(&args, files_to_link, file_count);
|
||||||
|
|||||||
@@ -22,8 +22,7 @@ void gencontext_begin_module(GenContext *c)
|
|||||||
}
|
}
|
||||||
const char *result = scratch_buffer_to_string();
|
const char *result = scratch_buffer_to_string();
|
||||||
c->ir_filename = strformat("%s.ll", result);
|
c->ir_filename = strformat("%s.ll", result);
|
||||||
// TODO filename should depend on platform.
|
c->object_filename = strformat("%s%s", result, DEFAULT_OBJ_FILE_EXT);
|
||||||
c->object_filename = strformat("%s.o", result);
|
|
||||||
|
|
||||||
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
c->module = LLVMModuleCreateWithNameInContext(c->code_module->name->module, c->context);
|
||||||
c->machine = llvm_target_machine_create();
|
c->machine = llvm_target_machine_create();
|
||||||
|
|||||||
@@ -226,12 +226,14 @@ Expr *parse_cond(Context *context)
|
|||||||
return decl_expr;
|
return decl_expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Expr* parse_expr(Context *context)
|
// These used to be explicitly inlined, but that seems to lead to confusing MSVC linker errors.
|
||||||
|
// They are probably still inlined by the compiler, though I haven't checked.
|
||||||
|
Expr* parse_expr(Context *context)
|
||||||
{
|
{
|
||||||
return parse_precedence(context, PREC_ASSIGNMENT);
|
return parse_precedence(context, PREC_ASSIGNMENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Expr* parse_constant_expr(Context *context)
|
Expr* parse_constant_expr(Context *context)
|
||||||
{
|
{
|
||||||
return parse_precedence(context, PREC_TERNARY);
|
return parse_precedence(context, PREC_TERNARY);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -989,6 +989,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl)
|
|||||||
{
|
{
|
||||||
DEBUG_LOG("----Analysing function %s", decl->name);
|
DEBUG_LOG("----Analysing function %s", decl->name);
|
||||||
Type *func_type = sema_analyse_function_signature(context, &decl->func_decl.function_signature, true);
|
Type *func_type = sema_analyse_function_signature(context, &decl->func_decl.function_signature, true);
|
||||||
|
|
||||||
decl->type = func_type;
|
decl->type = func_type;
|
||||||
if (!func_type) return decl_poison(decl);
|
if (!func_type) return decl_poison(decl);
|
||||||
if (decl->func_decl.type_parent)
|
if (decl->func_decl.type_parent)
|
||||||
|
|||||||
@@ -4,7 +4,10 @@
|
|||||||
|
|
||||||
#include "compiler_internal.h"
|
#include "compiler_internal.h"
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
// This isn't standard apparently, so MSVC doesn't have it built in...
|
||||||
|
typedef long long int ssize_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
static inline bool matches_subpath(Path *path_to_check, Path *path_to_find)
|
static inline bool matches_subpath(Path *path_to_check, Path *path_to_find)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,7 +3,13 @@
|
|||||||
// a copy of which can be found in the LICENSE file.
|
// a copy of which can be found in the LICENSE file.
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#define PATH_MAX 260
|
||||||
|
|
||||||
|
#else
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#endif
|
||||||
#include "compiler_internal.h"
|
#include "compiler_internal.h"
|
||||||
#include "../build/build_options.h"
|
#include "../build/build_options.h"
|
||||||
|
|
||||||
@@ -23,7 +29,11 @@ File *source_file_load(const char *filename, bool *already_loaded)
|
|||||||
if (already_loaded) *already_loaded = false;
|
if (already_loaded) *already_loaded = false;
|
||||||
if (!source_files.files) source_files.files = VECNEW(File *, LEXER_FILES_START_CAPACITY);
|
if (!source_files.files) source_files.files = VECNEW(File *, LEXER_FILES_START_CAPACITY);
|
||||||
|
|
||||||
char *full_path = malloc_arena(PATH_MAX + 1);
|
#ifdef _MSC_VER
|
||||||
|
char* full_path = malloc_arena(MAX_PATH + 1);
|
||||||
|
#else
|
||||||
|
char* full_path = malloc_arena(PATH_MAX + 1);
|
||||||
|
#endif
|
||||||
if (!realpath(filename, full_path))
|
if (!realpath(filename, full_path))
|
||||||
{
|
{
|
||||||
error_exit("Failed to resolve %s", filename);
|
error_exit("Failed to resolve %s", filename);
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ int main(int argc, const char *argv[])
|
|||||||
UNREACHABLE
|
UNREACHABLE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print_arena_status();
|
print_arena_status();
|
||||||
free_arena();
|
free_arena();
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
1030
src/utils/dirent.h
Normal file
1030
src/utils/dirent.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -6,18 +6,65 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
|
|
||||||
|
#if PLATFORM_WINDOWS
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _MSC_VER
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <unistd.h>
|
#else
|
||||||
|
#include "utils/dirent.h"
|
||||||
|
#define PATH_MAX 260
|
||||||
|
|
||||||
|
// dirname and basename on windows
|
||||||
|
#include "win_dirname_basename.h"
|
||||||
|
|
||||||
|
// copied from https://github.com/kindkaktus/libconfig/commit/d6222551c5c01c326abc99627e151d549e0f0958
|
||||||
|
#ifndef S_ISDIR
|
||||||
|
#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
|
||||||
|
#endif
|
||||||
|
// copied from https://stackoverflow.com/questions/11238918/s-isreg-macro-undefined
|
||||||
|
#if !defined(S_ISREG) && defined(S_IFMT) && defined(S_IFREG)
|
||||||
|
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include "whereami.h"
|
#include "whereami.h"
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* remove C: drive prefix (C:, D:, etc.) from a path. THIS WON'T WORK WITH D:, ETC.
|
||||||
|
* If that is an issue, I think dirent will have to be replaced or the dirent
|
||||||
|
* port in use will have to be replaced.
|
||||||
|
*/
|
||||||
|
char* strip_drive_prefix(char* path) {
|
||||||
|
if ((*path == 'c' || *path == 'C') && path[1] == ':') {
|
||||||
|
return path + 2; // remove first two characters
|
||||||
|
}
|
||||||
|
else if (path[1] == ':' && (path[2] == '/' || path[2] == '\\')) { // I don't *think* a relative path can start with '[char]:/' ? right?
|
||||||
|
// nothing can be done about this currently
|
||||||
|
error_exit("Illegal path %s - absolute path must start with /, \\, c:, or C: (file a github issue if this is a problem)");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// path is ok
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const char* expand_path(const char* path)
|
const char* expand_path(const char* path)
|
||||||
{
|
{
|
||||||
if (path[0] == '~' && path[1] == '/')
|
if (path[0] == '~' && path[1] == '/')
|
||||||
@@ -147,7 +194,11 @@ void file_find_top_dir()
|
|||||||
|
|
||||||
void file_add_wildcard_files(const char ***files, const char *path, bool recursive)
|
void file_add_wildcard_files(const char ***files, const char *path, bool recursive)
|
||||||
{
|
{
|
||||||
DIR *dir = opendir(path);
|
#ifdef _MSC_VER
|
||||||
|
DIR *dir = opendir(strip_drive_prefix(path));
|
||||||
|
#else
|
||||||
|
DIR* dir = opendir(path);
|
||||||
|
#endif
|
||||||
bool path_ends_with_slash = path[strlen(path) - 1] == '/';
|
bool path_ends_with_slash = path[strlen(path) - 1] == '/';
|
||||||
if (!dir)
|
if (!dir)
|
||||||
{
|
{
|
||||||
|
|||||||
79
src/utils/find_msvc.c
Normal file
79
src/utils/find_msvc.c
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#include "utils/common.h"
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
#include "utils/find_msvc.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "utils/dirent.h"
|
||||||
|
|
||||||
|
#define MSVC_BASE_PATH "/Program Files (x86)/Microsoft Visual Studio/"
|
||||||
|
#define WINKIT_BASE_PATH "/Program Files (x86)/Windows Kits/"
|
||||||
|
|
||||||
|
|
||||||
|
int is_numeric(const struct dirent* ent) {
|
||||||
|
return atoi(ent->d_name); // don't use this function if you expect a file named "0" ?
|
||||||
|
}
|
||||||
|
|
||||||
|
char* get_highest_ver(char* directory, int (*filter)(const struct dirent*)) {
|
||||||
|
struct dirent** files;
|
||||||
|
int num_files = scandir(directory, &files, filter, versionsort);
|
||||||
|
if (num_files < 0) {
|
||||||
|
error_exit("ERROR - Failed to autodetect MSVC libpaths\n");
|
||||||
|
}
|
||||||
|
char* path_ret = (char*)malloc(260);
|
||||||
|
strcpy_s(path_ret, 260, files[num_files - 1]->d_name);
|
||||||
|
for (int i = 0; i < num_files; i++) free(files[i]);
|
||||||
|
free(files);
|
||||||
|
return path_ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns PathPair containing paths to .../MSVC/[version]/lib/x64 and .../MSVC/[v]/atlmfc/lib/x64
|
||||||
|
*/
|
||||||
|
PathPair get_latest_available_vs_path() {
|
||||||
|
char ver_name[16] = "";
|
||||||
|
|
||||||
|
char* highest_ver = get_highest_ver(MSVC_BASE_PATH, is_numeric);
|
||||||
|
strncpy_s(ver_name, 16, highest_ver, 4);
|
||||||
|
free(highest_ver);
|
||||||
|
|
||||||
|
char newpath[260];
|
||||||
|
snprintf(newpath, 260, "%s%s/BuildTools/VC/Tools/MSVC/", MSVC_BASE_PATH, ver_name);
|
||||||
|
|
||||||
|
highest_ver = get_highest_ver(newpath, NULL);
|
||||||
|
strcat_s(newpath, 260, highest_ver);
|
||||||
|
free(highest_ver);
|
||||||
|
|
||||||
|
PathPair ret = { 0 };
|
||||||
|
snprintf(ret.first, 260, "%s/lib/x64", newpath);
|
||||||
|
snprintf(ret.second, 260, "%s/atlmfc/lib/x64", newpath);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns PathPair containing paths to /Program Files (x86)/Windows Kits/[version]/Lib/[version]/ucrt/x64 and .../[version]/um/x64
|
||||||
|
*/
|
||||||
|
PathPair find_winkit_path() {
|
||||||
|
// windows version
|
||||||
|
char win_ver_major[16] = "";
|
||||||
|
char* highest_ver = get_highest_ver(WINKIT_BASE_PATH, is_numeric);
|
||||||
|
strcpy_s(win_ver_major, 16, highest_ver);
|
||||||
|
free(highest_ver);
|
||||||
|
|
||||||
|
// windows kit version? or something
|
||||||
|
char newpath[260] = "";
|
||||||
|
sprintf_s(newpath, 260, "%s%s/Lib/", WINKIT_BASE_PATH, win_ver_major);
|
||||||
|
highest_ver = get_highest_ver(newpath, NULL);
|
||||||
|
strcat_s(newpath, 260, highest_ver);
|
||||||
|
free(highest_ver);
|
||||||
|
|
||||||
|
PathPair ret = { 0 };
|
||||||
|
snprintf(ret.first, 260, "%s/ucrt/x64", newpath);
|
||||||
|
snprintf(ret.second, 260, "%s/um/x64", newpath);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //defined(_MSC_VER)
|
||||||
9
src/utils/find_msvc.h
Normal file
9
src/utils/find_msvc.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char first[260];
|
||||||
|
char second[260];
|
||||||
|
} PathPair;
|
||||||
|
|
||||||
|
PathPair get_latest_available_vs_path();
|
||||||
|
PathPair find_winkit_path();
|
||||||
@@ -104,6 +104,21 @@ int vasnprintf(char **strp, const char *fmt, va_list args)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vasprintf(char** ret, const char* fmt, va_list args) {
|
||||||
|
int length = _vsnprintf(NULL, 0, fmt, args);
|
||||||
|
if (length < 0) { // check if _vsnprintf failed
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*ret = malloc(length + 1);
|
||||||
|
if (!*ret) { // check if malloc failed
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// Write String
|
||||||
|
_vsnprintf(*ret, length + 1, fmt, args);
|
||||||
|
(*ret)[length] = '\0'; // make sure there is a null terminator
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
char *strndup(const char *s, size_t n)
|
char *strndup(const char *s, size_t n)
|
||||||
{
|
{
|
||||||
n = strnlen(s, n);
|
n = strnlen(s, n);
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
// Use of this source code is governed by a LGPLv3.0
|
// Use of this source code is governed by a LGPLv3.0
|
||||||
// a copy of which can be found in the LICENSE file.
|
// a copy of which can be found in the LICENSE file.
|
||||||
|
|
||||||
|
|
||||||
#include "vmem.h"
|
#include "vmem.h"
|
||||||
|
|
||||||
#if PLATFORM_POSIX
|
#if PLATFORM_POSIX
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PLATFORM_WINDOWS
|
#if defined(WIN32)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#define COMMIT_PAGE_SIZE 0x10000
|
#define COMMIT_PAGE_SIZE 0x10000
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
|
|
||||||
// Code based off Gregory Pakosz's whereami.
|
// Code based off Gregory Pakosz's whereami.
|
||||||
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "whereami.h"
|
#include "whereami.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -32,7 +36,6 @@
|
|||||||
#pragma warning(push, 3)
|
#pragma warning(push, 3)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <intrin.h>
|
#include <intrin.h>
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
|
|||||||
64
src/utils/win_dirname_basename.h
Normal file
64
src/utils/win_dirname_basename.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// TODO I made these super quickly so they probably have some bugs from cases I didn't think of.
|
||||||
|
// A better implementation of these functions may be necessary.
|
||||||
|
|
||||||
|
char* basename(char* path)
|
||||||
|
{
|
||||||
|
size_t len = strlen(path);
|
||||||
|
size_t lastSlash = 0;
|
||||||
|
for (size_t i = len - 2; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (path[i] == '\\' || path[i] == '/')
|
||||||
|
{
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
// according to `man 3 basename` if there is no /, the original path should be returned
|
||||||
|
char* newStr = (char*)malloc(len);
|
||||||
|
strcpy(newStr, path);
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size_t newSize = len - lastSlash - 1;
|
||||||
|
char* newStr = (char*)malloc(newSize);
|
||||||
|
strncpy(newStr, path + lastSlash + 1, newSize);
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* dirname(char* path)
|
||||||
|
{
|
||||||
|
size_t len = strlen(path);
|
||||||
|
size_t lastSlash = 0;
|
||||||
|
for (size_t i = len - 2; i > 0; i--)
|
||||||
|
{
|
||||||
|
if (path[i] == '\\' || path[i] == '/')
|
||||||
|
{
|
||||||
|
if (i == len)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
lastSlash = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == 0)
|
||||||
|
{
|
||||||
|
// according to `man 3 basename` if there is no /, "." should be returned
|
||||||
|
char* newStr = (char*)malloc(2);
|
||||||
|
strcpy(newStr, ".");
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// size_t newSize = len - lastSlash - 1;
|
||||||
|
char* newStr = (char*)malloc(lastSlash);
|
||||||
|
strncpy(newStr, path, lastSlash);
|
||||||
|
return newStr;
|
||||||
|
}
|
||||||
29
windows_build.md
Normal file
29
windows_build.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
# Building and using C3C on windows
|
||||||
|
|
||||||
|
Windows support in C3C is currently experimental and unstable. It has many limitations and likely has bugs. With that aside, here's how you can build and use it:
|
||||||
|
|
||||||
|
## Compiling LLVM
|
||||||
|
|
||||||
|
First, follow the steps outlined here to set up and compile LLVM:
|
||||||
|
|
||||||
|
https://llvm.org/docs/GettingStartedVS.html
|
||||||
|
|
||||||
|
When running cmake, use the following options to enable all of the libraries needed by C3C:
|
||||||
|
|
||||||
|
```
|
||||||
|
cmake .. -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TARGETS_TO_BUILD="ARM;AArch64;RISCV;WebAssembly;X86" -Thost=x64
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compiling C3C
|
||||||
|
|
||||||
|
Clone the C3C github repository and open its directory in visual studio. VS should detect the CMake configuration, allowing you to simply use Build -> Build All to compile C3C. A `c3c.exe` will be placed in `out/build/build`.
|
||||||
|
|
||||||
|
## Using C3C on Windows
|
||||||
|
|
||||||
|
At this point, you should be able to use C3C normally. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
/c3c/out/build/build/c3c.exe compile ./hello_world.c3c
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that on windows, linker arguments passed through c3c using `-z` will need to be of the format expected by `lld-link`, which uses MSVC `link.exe`-format arguments rather than the GCC/Clang format.
|
||||||
Reference in New Issue
Block a user