mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Fix of arch target. Experimental linker support.
This commit is contained in:
committed by
Christoffer Lerno
parent
3a74c4adfc
commit
954a90dae3
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -13,9 +13,9 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- name: (Linux) Download LLVM
|
||||
run: |
|
||||
sudo apt-get install llvm-10
|
||||
sudo apt-get install libllvm11 llvm-11 llvm-11-dev llvm-11-runtime liblld-11-dev liblld-11
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build && cd build
|
||||
cmake -DLLVM_DIR=/usr/lib/llvm-10/cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake -DLLVM_DIR=/usr/lib/llvm-11/cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
cmake --build .
|
||||
|
||||
@@ -11,11 +11,13 @@ find_package(LLVM REQUIRED CONFIG)
|
||||
|
||||
message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
|
||||
message(STATUS "Using LLVMConfig.cmake in: ${LLVM_DIR}")
|
||||
message(STATUS "Libraries located in: ${LLVM_LIBRARY_DIRS}")
|
||||
|
||||
include_directories(${LLVM_INCLUDE_DIRS})
|
||||
add_definitions(${LLVM_DEFINITIONS})
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
set(LLVM_LINK_COMPONENTS
|
||||
AllTargetsAsmParsers
|
||||
@@ -42,14 +44,43 @@ set(LLVM_LINK_COMPONENTS
|
||||
native
|
||||
nativecodegen
|
||||
AsmPrinter
|
||||
Linker
|
||||
LTO
|
||||
Option
|
||||
WindowsManifest
|
||||
DebugInfoPDB
|
||||
LibDriver
|
||||
)
|
||||
|
||||
llvm_map_components_to_libnames(llvm_libs support core irreader ${LLVM_LINK_COMPONENTS})
|
||||
|
||||
llvm_map_components_to_libnames(llvm_libs ${LLVM_LINK_COMPONENTS})
|
||||
|
||||
file(COPY ${CMAKE_SOURCE_DIR}/resources/lib DESTINATION ${CMAKE_BINARY_DIR})
|
||||
|
||||
include_directories(
|
||||
"${CMAKE_SOURCE_DIR}/src/")
|
||||
find_library(LLD_COFF NAMES lldCOFF.a liblldCOFF.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||
find_library(LLD_COMMON NAMES lldCommon.a liblldCommon.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||
find_library(LLD_CORE NAMES lldCore.a liblldCore.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||
find_library(LLD_WASM NAMES lldWasm.a liblldWasm.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||
find_library(LLD_MINGW NAMES lldMinGW.a liblldMinGW.a PATHS ${LLVM_LIBRARY_DIRS})
|
||||
find_library(LLD_ELF NAMES lldELF.a liblldELF.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
|
||||
${LLD_COFF}
|
||||
${LLD_COMMON}
|
||||
${LLD_WASM}
|
||||
${LLD_MINGW}
|
||||
${LLD_ELF}
|
||||
${LLD_DRIVER}
|
||||
${LLD_READER_WRITER}
|
||||
${LLD_MACHO}
|
||||
${LLD_YAML}
|
||||
${LLD_CORE}
|
||||
)
|
||||
add_library(c3c_wrappers STATIC wrapper/src/wrapper.cpp)
|
||||
|
||||
add_executable(c3c
|
||||
src/main.c
|
||||
@@ -107,11 +138,29 @@ add_executable(c3c
|
||||
src/utils/vmem.c
|
||||
src/utils/vmem.h
|
||||
src/utils/whereami.c
|
||||
src/compiler/llvm_codegen_c_abi_x86.c src/compiler/c_abi_internal.h src/compiler/llvm_codegen_c_abi_x64.c src/compiler/llvm_codegen_c_abi_win64.c src/compiler/llvm_codegen_c_abi_aarch64.c src/compiler/headers.c src/compiler/llvm_codegen_c_abi_riscv.c src/compiler/llvm_codegen_c_abi_wasm.c)
|
||||
src/compiler/llvm_codegen_c_abi_x86.c
|
||||
src/compiler/c_abi_internal.h
|
||||
src/compiler/llvm_codegen_c_abi_x64.c
|
||||
src/compiler/llvm_codegen_c_abi_win64.c
|
||||
src/compiler/llvm_codegen_c_abi_aarch64.c
|
||||
src/compiler/headers.c
|
||||
src/compiler/llvm_codegen_c_abi_riscv.c
|
||||
src/compiler/llvm_codegen_c_abi_wasm.c)
|
||||
|
||||
target_compile_options(c3c PRIVATE -Wsign-compare -Wimplicit-int -Werror -Wall -Wno-unknown-pragmas -Wextra -Wno-unused-function -Wno-unused-variable -Wno-unused-parameter)
|
||||
|
||||
target_link_libraries(c3c m ${llvm_libs})
|
||||
target_include_directories(c3c PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/src/")
|
||||
|
||||
target_include_directories(c3c_wrappers PRIVATE
|
||||
"${CMAKE_SOURCE_DIR}/wrapper/src/")
|
||||
|
||||
|
||||
message(STATUS "Found LLD ${lld_libs}")
|
||||
|
||||
target_link_libraries(c3c_wrappers ${llvm_libs} ${lld_libs})
|
||||
#target_link_libraries(c3c m ${llvm_libs} c3c_wrappers lldCommon lldCore lldCOFF lldWASM lldMinGW lldELF lldDriver lldReaderWriter lldMachO lldYAML)
|
||||
target_link_libraries(c3c m ${llvm_libs} c3c_wrappers ${lld_libs})
|
||||
|
||||
install(TARGETS c3c DESTINATION bin)
|
||||
|
||||
|
||||
@@ -330,7 +330,7 @@ static void parse_option(BuildOptions *options)
|
||||
if (at_end() || next_is_opt()) error_exit("error: --target needs a arch+os definition.");
|
||||
const char *target = next_arg();
|
||||
ArchOsTarget target_arch_os = arch_os_target_from_string(target);
|
||||
if (target_arch_os >= 0)
|
||||
if (target_arch_os != ARCH_OS_TARGET_DEFAULT)
|
||||
{
|
||||
options->arch_os_target_override = target_arch_os;
|
||||
return;
|
||||
@@ -473,5 +473,5 @@ ArchOsTarget arch_os_target_from_string(const char *target)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return ARCH_OS_TARGET_DEFAULT;
|
||||
}
|
||||
@@ -31,9 +31,9 @@ void compiler_init(void)
|
||||
vmem_init(&tokdata_arena, 4 * 1024);
|
||||
vmem_init(&type_info_arena, 1024);
|
||||
// Create zero index value.
|
||||
SourceLocation *loc = sourceloc_calloc();
|
||||
char *token_type = toktype_calloc();
|
||||
TokenData *data = tokdata_calloc();
|
||||
(void) sourceloc_calloc();
|
||||
(void) toktype_calloc();
|
||||
(void) tokdata_calloc();
|
||||
compiler.lib_dir = find_lib_dir();
|
||||
}
|
||||
|
||||
@@ -172,9 +172,7 @@ void compiler_compile(BuildTarget *target)
|
||||
|
||||
|
||||
bool create_exe = !target->test_output && (target->type == TARGET_TYPE_EXECUTABLE || target->type == TARGET_TYPE_TEST);
|
||||
#if PLATFORM_WINDOWS
|
||||
create_exe = false;
|
||||
#endif
|
||||
|
||||
const char **obj_files = NULL;
|
||||
|
||||
for (unsigned i = 0; i < source_count; i++)
|
||||
@@ -184,7 +182,7 @@ void compiler_compile(BuildTarget *target)
|
||||
vec_add(obj_files, file_name);
|
||||
}
|
||||
|
||||
if (create_exe)
|
||||
if (create_exe && obj_format_linking_supported(platform_target.object_format))
|
||||
{
|
||||
linker(target->name, obj_files, source_count);
|
||||
if (target->run_after_compile)
|
||||
|
||||
@@ -1441,7 +1441,7 @@ static inline Ast *extend_ast_with_prev_token(Context *context, Ast *ast)
|
||||
|
||||
|
||||
|
||||
void builtin_setup(Target *target);
|
||||
void builtin_setup(PlatformTarget *target);
|
||||
|
||||
static inline bool builtin_may_negate(Type *canonical)
|
||||
{
|
||||
@@ -1554,27 +1554,24 @@ void lexer_init_for_test(Lexer *lexer, const char *text, size_t len);
|
||||
void lexer_init_with_file(Lexer *lexer, File *file);
|
||||
File* lexer_current_file(Lexer *lexer);
|
||||
|
||||
static inline SourceLocation *TOKILOC(TokenId token) { return sourcelocptr(token.index); }
|
||||
static inline SourceLocation *TOKKLOC(Token token) { return sourcelocptr(token.id.index); }
|
||||
|
||||
static inline SourceLocation *tokenid_loc(TokenId token) { return sourcelocptr(token.index); }
|
||||
static inline SourceLocation *token_loc(Token token) { return sourcelocptr(token.id.index); }
|
||||
static inline TokenData *tokendata_from_id(TokenId token) { return tokdataptr(token.index); }
|
||||
static inline TokenData *tokendata_from_token(Token token) { return tokdataptr(token.id.index); }
|
||||
|
||||
#define TOKLOC(T) _Generic((T), TokenId: TOKILOC, Token: TOKKLOC)(T)
|
||||
#define TOKDATA(T) _Generic((T), TokenId: tokendata_from_id, Token: tokendata_from_token)(T)
|
||||
#define TOKLOC(T) _Generic((T), TokenId: tokenid_loc, Token: token_loc)(T)
|
||||
|
||||
static inline const char *TOKISTR(TokenId token) { return tokendata_from_id(token)->string; }
|
||||
static inline const char *TOKKSTR(Token token) { return tokendata_from_id(token.id)->string; }
|
||||
#define TOKSTR(T) _Generic((T), TokenId: TOKISTR, Token: TOKKSTR)(T)
|
||||
#define TOKSTR(T) TOKDATA(T)->string
|
||||
|
||||
static inline double TOKIREAL(TokenId token) { return tokendata_from_id(token)->value; }
|
||||
static inline double TOKKREAL(Token token) { return tokendata_from_id(token.id)->value; }
|
||||
#define TOKREAL(T) _Generic((T), TokenId: TOKIREAL, Token: TOKKREAL)(T)
|
||||
#define TOKREAL(T) TOKDATA(T)->value
|
||||
|
||||
static inline TokenType TOKITYPE(TokenId token) { return toktypeptr(token.index)[0]; }
|
||||
static inline TokenType TOKKTYPE(Token token) { return toktypeptr(token.id.index)[0]; }
|
||||
#define TOKTYPE(T) _Generic((T), TokenId: TOKITYPE, Token: TOKKTYPE)(T)
|
||||
static inline TokenType tokenid_type(TokenId token) { return toktypeptr(token.index)[0]; }
|
||||
static inline TokenType token_type(Token token) { return toktypeptr(token.id.index)[0]; }
|
||||
#define TOKTYPE(T) _Generic((T), TokenId: tokenid_type, Token: token_type)(T)
|
||||
|
||||
static inline uint32_t TOKILEN(TokenId token) { return TOKILOC(token)->length; }
|
||||
static inline uint32_t TOKKLEN(Token token) { return TOKKLOC(token)->length; }
|
||||
#define TOKLEN(T) _Generic((T), TokenId: TOKILEN, Token:TOKKLEN)(T)
|
||||
#define TOKLEN(T) TOKLOC(T)->length
|
||||
|
||||
#define TOKVALID(_tok) (_tok.index != 0)
|
||||
Decl *module_find_symbol(Module *module, const char *symbol, ModuleSymbolSearch search, Decl **private_decl);
|
||||
@@ -2000,8 +1997,10 @@ static inline size_t type_min_alignment(size_t a, size_t b)
|
||||
return (a | b) & (1 + ~(a | b));
|
||||
}
|
||||
|
||||
bool obj_format_linking_supported(ObjectFormatType format_type);
|
||||
void linker(const char *output_file, const char **files, unsigned file_count);
|
||||
|
||||
|
||||
#define TRY_AST_OR(_ast_stmt, _res) ({ Ast* _ast = (_ast_stmt); if (!ast_ok(_ast)) return _res; _ast; })
|
||||
#define TRY_EXPR_OR(_expr_stmt, _res) ({ Expr* _expr = (_expr_stmt); if (!expr_ok(_expr)) return _res; _expr; })
|
||||
#define TRY_TYPE_OR(_type_stmt, _res) ({ TypeInfo* _type = (_type_stmt); if (!type_info_ok(_type)) return _res; _type; })
|
||||
|
||||
@@ -191,8 +191,8 @@ bool context_add_import(Context *context, Path *path, Token token, Token alias)
|
||||
import->import.symbol = token.id;
|
||||
if (alias.type != TOKEN_INVALID_TOKEN)
|
||||
{
|
||||
const char *alias_name = TOKKSTR(alias);
|
||||
if (alias_name == TOKKSTR(token))
|
||||
const char *alias_name = TOKSTR(alias);
|
||||
if (alias_name == TOKSTR(token))
|
||||
{
|
||||
SEMA_TOKEN_ERROR(alias, "If an alias would be the same as the symbol aliased, it wouldn't have any effect.");
|
||||
return false;
|
||||
|
||||
@@ -636,7 +636,7 @@ static inline bool scan_char(Lexer *lexer)
|
||||
lexer->lexing_start = start;
|
||||
return add_error_token(lexer, "Expected a four character hex value after \\u.");
|
||||
}
|
||||
if (build_target.little_endian)
|
||||
if (platform_target.little_endian)
|
||||
{
|
||||
bytes.b[width++] = hex & 0xFF;
|
||||
bytes.b[width++] = hex >> 8;
|
||||
@@ -656,7 +656,7 @@ static inline bool scan_char(Lexer *lexer)
|
||||
lexer->lexing_start = start;
|
||||
return add_error_token(lexer, "Expected an eight character hex value after \\U.");
|
||||
}
|
||||
if (build_target.little_endian)
|
||||
if (platform_target.little_endian)
|
||||
{
|
||||
bytes.b[width++] = hex & 0xFF;
|
||||
bytes.b[width++] = (hex >> 8) & 0xFF;
|
||||
|
||||
@@ -1,30 +1,86 @@
|
||||
#include "compiler_internal.h"
|
||||
|
||||
#if PLATFORM_WINDOWS
|
||||
static void link_exe(const char *output_file, const char **files_to_link, unsigned file_count)
|
||||
{
|
||||
TODO
|
||||
}
|
||||
#else
|
||||
static void link_exe(const char *output_file, const char **files_to_link, unsigned file_count)
|
||||
{
|
||||
char *result = NULL;
|
||||
asprintf(&result, "cc -o %s ", output_file);
|
||||
extern bool llvm_link_elf(const char **args, int arg_count, const char** error_string);
|
||||
extern bool llvm_link_macho(const char **args, int arg_count, const char** error_string);
|
||||
extern bool llvm_link_coff(const char **args, int arg_count, const char** error_string);
|
||||
extern bool llvm_link_wasm(const char **args, int arg_count, const char** error_string);
|
||||
extern bool llvm_link_mingw(const char **args, int arg_count, const char** error_string);
|
||||
|
||||
static void link_exe(const char *output_file, const char **files_to_link, unsigned file_count)
|
||||
{
|
||||
int arg_count = (int)file_count + 2;
|
||||
const char **args = NULL;
|
||||
vec_add(args, "-o");
|
||||
vec_add(args, output_file);
|
||||
vec_add(args, "-m");
|
||||
vec_add(args, platform_target.target_triple);
|
||||
for (unsigned i = 0; i < file_count; i++)
|
||||
{
|
||||
char *new_res = NULL;
|
||||
asprintf(&new_res, "%s %s", result, files_to_link[i]);
|
||||
free(result);
|
||||
result = new_res;
|
||||
args[i + 2] = files_to_link[i];
|
||||
}
|
||||
if (system(result) != EXIT_SUCCESS)
|
||||
const char *error = NULL;
|
||||
|
||||
switch (platform_target.os)
|
||||
{
|
||||
error_exit("Failed to create an executable.");
|
||||
case OS_TYPE_WIN32:
|
||||
break;
|
||||
case OS_TYPE_WATCHOS:
|
||||
case OS_TYPE_MACOSX:
|
||||
vec_add(args, "-lSystem");
|
||||
vec_add(args, "-lm");
|
||||
vec_add(args, "-syslibroot");
|
||||
vec_add(args, "/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk");
|
||||
break;
|
||||
case OS_TYPE_LINUX:
|
||||
vec_add(args, "-lc");
|
||||
vec_add(args, "-lm");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bool success;
|
||||
switch (platform_target.object_format)
|
||||
{
|
||||
case OBJ_FORMAT_COFF:
|
||||
success = llvm_link_coff(args, arg_count, &error);
|
||||
break;
|
||||
case OBJ_FORMAT_ELF:
|
||||
success = llvm_link_elf(args, arg_count, &error);
|
||||
break;
|
||||
case OBJ_FORMAT_MACHO:
|
||||
success = llvm_link_macho(args, arg_count, &error);
|
||||
break;
|
||||
case OBJ_FORMAT_WASM:
|
||||
success = llvm_link_wasm(args, arg_count, &error);
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (!success)
|
||||
{
|
||||
error_exit("Failed to create an executable: %s", error);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool obj_format_linking_supported(ObjectFormatType format_type)
|
||||
{
|
||||
switch (format_type)
|
||||
{
|
||||
case OBJ_FORMAT_XCOFF:
|
||||
case OBJ_FORMAT_AOUT:
|
||||
case OBJ_FORMAT_GOFF:
|
||||
case OBJ_FORMAT_UNSUPPORTED:
|
||||
return false;
|
||||
case OBJ_FORMAT_COFF:
|
||||
case OBJ_FORMAT_ELF:
|
||||
case OBJ_FORMAT_MACHO:
|
||||
case OBJ_FORMAT_WASM:
|
||||
return true;
|
||||
}
|
||||
UNREACHABLE
|
||||
|
||||
}
|
||||
void linker(const char *output_file, const char **files, unsigned file_count)
|
||||
{
|
||||
link_exe(output_file, files, file_count);
|
||||
|
||||
@@ -419,7 +419,7 @@ static void gencontext_verify_ir(GenContext *context)
|
||||
void gencontext_emit_object_file(GenContext *context)
|
||||
{
|
||||
char *err = "";
|
||||
LLVMSetTarget(context->module, build_target.target_triple);
|
||||
LLVMSetTarget(context->module, platform_target.target_triple);
|
||||
char *layout = LLVMCopyStringRepOfTargetData(target_data_layout());
|
||||
LLVMSetDataLayout(context->module, layout);
|
||||
LLVMDisposeMessage(layout);
|
||||
|
||||
@@ -183,7 +183,7 @@ ABIArgInfo *abi_arg_new_expand_padded(Type *padding)
|
||||
|
||||
void c_abi_func_create(FunctionSignature *signature)
|
||||
{
|
||||
switch (build_target.abi)
|
||||
switch (platform_target.abi)
|
||||
{
|
||||
case ABI_X64:
|
||||
c_abi_func_create_x64(signature);
|
||||
@@ -223,7 +223,7 @@ ABIArgInfo *c_abi_classify_argument_type_default(Type *type)
|
||||
// Struct-likes are returned by sret
|
||||
if (type_is_abi_aggregate(type)) return abi_arg_new_indirect_by_val();
|
||||
|
||||
if (type_is_int128(type) && !build_target.int_128) return abi_arg_new_indirect_by_val();
|
||||
if (type_is_int128(type) && !platform_target.int128) return abi_arg_new_indirect_by_val();
|
||||
|
||||
// Otherwise do we have a type that needs promotion?
|
||||
if (type_is_promotable_integer(type)) return abi_arg_new_direct_int_ext(type);
|
||||
|
||||
@@ -32,7 +32,7 @@ ABIArgInfo *aarch64_classify_argument_type(Type *type)
|
||||
{
|
||||
// Over 128 bits should be indirect, but
|
||||
// we don't have that (yet?)
|
||||
if (type_is_promotable_integer(type) && build_target.aarch64.is_darwin_pcs)
|
||||
if (type_is_promotable_integer(type) && platform_target.aarch64.is_darwin_pcs)
|
||||
{
|
||||
return abi_arg_new_direct_int_ext(type);
|
||||
}
|
||||
@@ -57,7 +57,7 @@ ABIArgInfo *aarch64_classify_argument_type(Type *type)
|
||||
{
|
||||
// For RenderScript <= 16 needs to be coerced.
|
||||
AlignSize alignment = type_abi_alignment(type);
|
||||
if (build_target.aarch64.is_aapcs)
|
||||
if (platform_target.aarch64.is_aapcs)
|
||||
{
|
||||
alignment = alignment < 16 ? 8 : 16;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ ABIArgInfo *aarch64_classify_return_type(Type *type, bool variadic)
|
||||
|
||||
if (!type_is_abi_aggregate(type))
|
||||
{
|
||||
if (type_is_promotable_integer(type) && build_target.aarch64.is_darwin_pcs)
|
||||
if (type_is_promotable_integer(type) && platform_target.aarch64.is_darwin_pcs)
|
||||
{
|
||||
return abi_arg_new_direct_int_ext(type);
|
||||
}
|
||||
@@ -115,7 +115,7 @@ ABIArgInfo *aarch64_classify_return_type(Type *type, bool variadic)
|
||||
Type *base = NULL;
|
||||
unsigned members = 0;
|
||||
if (type_is_homogenous_aggregate(type, &base, &members) &&
|
||||
!(build_target.arch == ARCH_TYPE_AARCH64_32 && variadic))
|
||||
!(platform_target.arch == ARCH_TYPE_AARCH64_32 && variadic))
|
||||
{
|
||||
return abi_arg_ignore();
|
||||
}
|
||||
|
||||
@@ -36,11 +36,11 @@ static bool riscv_detect_fpcc_struct_internal(Type *type, unsigned current_offse
|
||||
{
|
||||
bool is_int = type_is_integer(type);
|
||||
bool is_float = type_is_float(type);
|
||||
unsigned flen = build_target.riscv.flen;
|
||||
unsigned flen = platform_target.riscv.flen;
|
||||
unsigned size = type_size(type);
|
||||
if (is_int || is_float)
|
||||
{
|
||||
if (is_int && size > build_target.riscv.xlen) return false;
|
||||
if (is_int && size > platform_target.riscv.xlen) return false;
|
||||
// Can't be eligible if larger than the FP registers. Half precision isn't
|
||||
// currently supported on RISC-V and the ABI hasn't been confirmed, so
|
||||
// default to the integer ABI in that case.
|
||||
@@ -162,7 +162,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
|
||||
assert(type == type->canonical);
|
||||
|
||||
unsigned xlen = build_target.riscv.xlen;
|
||||
unsigned xlen = platform_target.riscv.xlen;
|
||||
|
||||
// Ignore empty structs/unions.
|
||||
if (type_is_empty_union_struct(type, true)) return abi_arg_ignore();
|
||||
@@ -170,7 +170,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
ByteSize size = type_size(type);
|
||||
|
||||
// Pass floating point values via FPRs if possible.
|
||||
if (is_fixed && type_is_float(type) && build_target.riscv.flen >= size && *fprs)
|
||||
if (is_fixed && type_is_float(type) && platform_target.riscv.flen >= size && *fprs)
|
||||
{
|
||||
(*fprs)--;
|
||||
return abi_arg_new_direct();
|
||||
@@ -181,7 +181,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
if (is_fixed && type->type_kind == TYPE_COMPLEX && *fprs >= 2)
|
||||
{
|
||||
Type *element_type = type->complex;
|
||||
if (type_size(element_type) <= build_target.riscv.flen)
|
||||
if (type_size(element_type) <= platform_target.riscv.flen)
|
||||
{
|
||||
(*fprs) -= 2;
|
||||
// TODO check that this will expand correctly.
|
||||
@@ -189,7 +189,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
}
|
||||
}
|
||||
|
||||
if (is_fixed && build_target.riscv.flen && (type->type_kind == TYPE_STRUCT || type->type_kind == TYPE_ERRTYPE))
|
||||
if (is_fixed && platform_target.riscv.flen && (type->type_kind == TYPE_STRUCT || type->type_kind == TYPE_ERRTYPE))
|
||||
{
|
||||
AbiType *field1 = NULL;
|
||||
AbiType *field2 = NULL;
|
||||
@@ -242,7 +242,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
{
|
||||
return abi_arg_new_expand_padded(type_int_unsigned_by_bitsize(xlen * 8));
|
||||
}
|
||||
if (size > 16 || (size > 8 && !build_target.int_128))
|
||||
if (size > 16 || (size > 8 && !platform_target.int128))
|
||||
{
|
||||
return abi_arg_new_indirect_not_by_val();
|
||||
}
|
||||
@@ -259,7 +259,7 @@ static ABIArgInfo *riscv_classify_argument_type(Type *type, bool is_fixed, unsig
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(xlen * 8));
|
||||
}
|
||||
if (alignment == 2 * build_target.riscv.xlen)
|
||||
if (alignment == 2 * platform_target.riscv.xlen)
|
||||
{
|
||||
return abi_arg_new_direct_coerce(abi_type_new_int_bits(xlen * 16));
|
||||
}
|
||||
@@ -275,7 +275,7 @@ static ABIArgInfo *riscv_classify_return(Type *return_type)
|
||||
if (return_type->type_kind == TYPE_VOID) return abi_arg_ignore();
|
||||
|
||||
unsigned arg_gpr_left = 2;
|
||||
unsigned arg_fpr_left = build_target.riscv.flen ? 2 : 0;
|
||||
unsigned arg_fpr_left = platform_target.riscv.flen ? 2 : 0;
|
||||
|
||||
// The rules for return and argument types are the same, so defer to
|
||||
// classifyArgumentType.
|
||||
@@ -306,11 +306,11 @@ void c_abi_func_create_riscv(FunctionSignature *signature)
|
||||
// in LLVM IR, relying on the backend lowering code to rewrite the argument
|
||||
// list and pass indirectly on RV32.
|
||||
bool is_ret_indirect = abi_arg_is_indirect(return_abi);
|
||||
if (!is_ret_indirect && type_is_scalar(return_type) && type_size(return_type) > 2 * build_target.riscv.xlen)
|
||||
if (!is_ret_indirect && type_is_scalar(return_type) && type_size(return_type) > 2 * platform_target.riscv.xlen)
|
||||
{
|
||||
if (return_type->type_kind == TYPE_COMPLEX && build_target.riscv.flen)
|
||||
if (return_type->type_kind == TYPE_COMPLEX && platform_target.riscv.flen)
|
||||
{
|
||||
is_ret_indirect = type_size(return_type->complex) > build_target.riscv.flen;
|
||||
is_ret_indirect = type_size(return_type->complex) > platform_target.riscv.flen;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -324,7 +324,7 @@ void c_abi_func_create_riscv(FunctionSignature *signature)
|
||||
// different for variadic arguments, we must also track whether we are
|
||||
// examining a vararg or not.
|
||||
unsigned arg_gprs_left = is_ret_indirect ? gpr - 1 : gpr;
|
||||
unsigned arg_fprs_left = build_target.riscv.flen ? fpr : 0;
|
||||
unsigned arg_fprs_left = platform_target.riscv.flen ? fpr : 0;
|
||||
|
||||
// If we have a failable, then the return type is a parameter.
|
||||
if (signature->failable && signature->rtype->type->type_kind != TYPE_VOID)
|
||||
|
||||
@@ -53,7 +53,7 @@ ABIArgInfo *x64_indirect_return_result(Type *type)
|
||||
}
|
||||
static ByteSize x64_native_vector_size_for_avx(void)
|
||||
{
|
||||
switch (build_target.x64.avx_level)
|
||||
switch (platform_target.x64.avx_level)
|
||||
{
|
||||
case AVX_NONE:
|
||||
return 16;
|
||||
@@ -74,7 +74,7 @@ static bool x64_type_is_illegal_vector(Type *type)
|
||||
// Less than 64 bits or larger than the avx native size => not allowed.
|
||||
if (size <= 8 || size > x64_native_vector_size_for_avx()) return true;
|
||||
// If we pass i128 in mem, then check for that.
|
||||
if (build_target.x64.pass_int128_vector_in_mem)
|
||||
if (platform_target.x64.pass_int128_vector_in_mem)
|
||||
{
|
||||
// Illegal if i128/u128
|
||||
TypeKind kind = type->vector.base->type_kind;
|
||||
@@ -354,7 +354,7 @@ void x64_classify_vector(Type *type, ByteSize offset_base, X64Class *current, X6
|
||||
}
|
||||
if (size == 16 || named_arg || size <= x64_native_vector_size_for_avx())
|
||||
{
|
||||
if (build_target.x64.pass_int128_vector_in_mem) return;
|
||||
if (platform_target.x64.pass_int128_vector_in_mem) return;
|
||||
|
||||
*lo_class = CLASS_SSE;
|
||||
*hi_class = CLASS_SSEUP;
|
||||
@@ -668,7 +668,7 @@ static AbiType *x64_get_byte_vector_type(Type *type)
|
||||
if (type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
Type *element = type->vector.base->canonical;
|
||||
if (build_target.x64.pass_int128_vector_in_mem && type_is_int128(element))
|
||||
if (platform_target.x64.pass_int128_vector_in_mem && type_is_int128(element))
|
||||
{
|
||||
// Convert to u64
|
||||
return abi_type_new_plain(type_get_vector(type_ulong, type_size(type) / 8));
|
||||
|
||||
@@ -35,7 +35,7 @@ static unsigned x86_stack_alignment(Type *type, unsigned alignment)
|
||||
if (alignment < MIN_ABI_STACK_ALIGN) return 0;
|
||||
|
||||
// On non-Darwin, the stack type alignment is always 4.
|
||||
if (!build_target.x86.is_darwin_vector_abi) return MIN_ABI_STACK_ALIGN;
|
||||
if (!platform_target.x86.is_darwin_vector_abi) return MIN_ABI_STACK_ALIGN;
|
||||
|
||||
// Otherwise, if the type contains an SSE vector type, the alignment is 16.
|
||||
if (alignment >= 16 && (type_is_simd_vector(type) || type_is_union_struct_with_simd_vector(type)))
|
||||
@@ -55,7 +55,7 @@ static ABIArgInfo *x86_create_indirect_result(Regs *regs, Type *type, ByVal by_v
|
||||
if (regs->int_regs)
|
||||
{
|
||||
regs->int_regs--;
|
||||
if (!build_target.x86.is_mcu_api) info->attributes.by_reg = true;
|
||||
if (!platform_target.x86.is_mcu_api) info->attributes.by_reg = true;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ ABIArgInfo *create_indirect_return_x86(Regs *regs)
|
||||
if (!regs->int_regs) return info;
|
||||
// Consume a register for the return.
|
||||
regs->int_regs--;
|
||||
if (build_target.x86.is_mcu_api) return info;
|
||||
if (platform_target.x86.is_mcu_api) return info;
|
||||
|
||||
return abi_arg_by_reg_attr(info);
|
||||
}
|
||||
@@ -97,7 +97,7 @@ static bool x86_should_return_type_in_reg(Type *type)
|
||||
if (size > 8) return false;
|
||||
|
||||
// Require power of two for everything except mcu.
|
||||
if (!build_target.x86.is_mcu_api && !is_power_of_two(size)) return false;
|
||||
if (!platform_target.x86.is_mcu_api && !is_power_of_two(size)) return false;
|
||||
|
||||
if (type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
@@ -172,7 +172,7 @@ ABIArgInfo *x86_classify_return(CallConvention call, Regs *regs, Type *type)
|
||||
if (type->type_kind == TYPE_VECTOR)
|
||||
{
|
||||
// On Darwin, vectors may be returned in registers.
|
||||
if (build_target.x86.is_darwin_vector_abi)
|
||||
if (platform_target.x86.is_darwin_vector_abi)
|
||||
{
|
||||
unsigned size = type_size(type);
|
||||
if (size == 16)
|
||||
@@ -194,7 +194,7 @@ ABIArgInfo *x86_classify_return(CallConvention call, Regs *regs, Type *type)
|
||||
if (type_is_abi_aggregate(type))
|
||||
{
|
||||
// If we don't allow small structs in reg:
|
||||
if (!build_target.x86.return_small_struct_in_reg_abi && type->type_kind == TYPE_COMPLEX)
|
||||
if (!platform_target.x86.return_small_struct_in_reg_abi && type->type_kind == TYPE_COMPLEX)
|
||||
{
|
||||
return create_indirect_return_x86(regs);
|
||||
}
|
||||
@@ -212,7 +212,7 @@ ABIArgInfo *x86_classify_return(CallConvention call, Regs *regs, Type *type)
|
||||
Type *single_element = type_abi_find_single_struct_element(type);
|
||||
if (single_element)
|
||||
{
|
||||
if ((type_is_float(single_element) && !build_target.x86.is_win32_float_struct_abi))
|
||||
if ((type_is_float(single_element) && !platform_target.x86.is_win32_float_struct_abi))
|
||||
{
|
||||
return abi_arg_new_expand();
|
||||
}
|
||||
@@ -246,13 +246,13 @@ static inline bool x86_should_aggregate_use_direct(CallConvention call, Regs *re
|
||||
// On Windows, aggregates other than HFAs are never passed in registers, and
|
||||
// they do not consume register slots. Homogenous floating-point aggregates
|
||||
// (HFAs) have already been dealt with at this point.
|
||||
if (build_target.x86.is_win32_float_struct_abi) return false;
|
||||
if (platform_target.x86.is_win32_float_struct_abi) return false;
|
||||
|
||||
*needs_padding = false;
|
||||
|
||||
if (!x86_try_use_free_regs(regs, type)) return false;
|
||||
|
||||
if (build_target.x86.is_mcu_api) return true;
|
||||
if (platform_target.x86.is_mcu_api) return true;
|
||||
|
||||
switch (call)
|
||||
{
|
||||
@@ -324,7 +324,7 @@ static inline bool x86_can_expand_indirect_aggregate_arg(Type *type)
|
||||
static bool x86_try_use_free_regs(Regs *regs, Type *type)
|
||||
{
|
||||
// 1. Floats are not passed in regs on soft floats.
|
||||
if (!build_target.x86.use_soft_float && type_is_float(type)) return false;
|
||||
if (!platform_target.x86.use_soft_float && type_is_float(type)) return false;
|
||||
|
||||
unsigned size = type_size(type);
|
||||
|
||||
@@ -338,7 +338,7 @@ static bool x86_try_use_free_regs(Regs *regs, Type *type)
|
||||
// earlier parameters that are passed on the stack. Also,
|
||||
// it does not allow passing >8-byte structs in-register,
|
||||
// even if there are 3 free registers available.
|
||||
if (build_target.x86.is_mcu_api)
|
||||
if (platform_target.x86.is_mcu_api)
|
||||
{
|
||||
// 4a. Just return if there are not enough registers.
|
||||
if (size_in_regs > regs->int_regs) return false;
|
||||
@@ -377,7 +377,7 @@ static bool x86_try_put_primitive_in_reg(CallConvention call, Regs *regs, Type *
|
||||
if (!x86_try_use_free_regs(regs, type)) return false;
|
||||
|
||||
// 2. On MCU, do not use the inreg attribute.
|
||||
if (build_target.x86.is_mcu_api) return false;
|
||||
if (platform_target.x86.is_mcu_api) return false;
|
||||
|
||||
// 3. Reg/fast/vec calls limit it to 32 bits
|
||||
// and integer / pointer types.
|
||||
@@ -442,7 +442,7 @@ static inline ABIArgInfo *x86_classify_vector(Regs *regs, Type *type)
|
||||
// On Windows, vectors are passed directly if registers are available, or
|
||||
// indirectly if not. This avoids the need to align argument memory. Pass
|
||||
// user-defined vector types larger than 512 bits indirectly for simplicity.
|
||||
if (build_target.x86.is_win32_float_struct_abi)
|
||||
if (platform_target.x86.is_win32_float_struct_abi)
|
||||
{
|
||||
if (size < 64 && regs->float_regs)
|
||||
{
|
||||
@@ -453,7 +453,7 @@ static inline ABIArgInfo *x86_classify_vector(Regs *regs, Type *type)
|
||||
}
|
||||
// On Darwin, some vectors are passed in memory, we handle this by passing
|
||||
// it as an i8/i16/i32/i64.
|
||||
if (build_target.x86.is_darwin_vector_abi)
|
||||
if (platform_target.x86.is_darwin_vector_abi)
|
||||
{
|
||||
if ((size == 1 || size == 2 || size == 4) || (size == 8 && type->vector.len == 1))
|
||||
{
|
||||
@@ -481,7 +481,7 @@ static inline ABIArgInfo *x86_classify_aggregate(CallConvention call, Regs *regs
|
||||
assert(type_is_abi_aggregate(type));
|
||||
|
||||
// Ignore empty unions / structs on non-win.
|
||||
if (!build_target.x86.is_win32_float_struct_abi && type_is_empty_union_struct(type, true))
|
||||
if (!platform_target.x86.is_win32_float_struct_abi && type_is_empty_union_struct(type, true))
|
||||
{
|
||||
return abi_arg_ignore();
|
||||
}
|
||||
@@ -491,7 +491,7 @@ static inline ABIArgInfo *x86_classify_aggregate(CallConvention call, Regs *regs
|
||||
|
||||
// Pass over-aligned aggregates on Windows indirectly. This behavior was
|
||||
// added in MSVC 2015.
|
||||
if (build_target.x86.is_win32_float_struct_abi && type_abi_alignment(type) > 4)
|
||||
if (platform_target.x86.is_win32_float_struct_abi && type_abi_alignment(type) > 4)
|
||||
{
|
||||
return x86_create_indirect_result(regs, type, BY_VAL_SKIP);
|
||||
}
|
||||
@@ -506,7 +506,7 @@ static inline ABIArgInfo *x86_classify_aggregate(CallConvention call, Regs *regs
|
||||
ABIArgInfo *info = abi_arg_new_direct_coerce(abi_type_new_int_bits(32));
|
||||
info->direct_coerce.elements = size_in_regs;
|
||||
// Not in reg on MCU
|
||||
if (!build_target.x86.is_mcu_api) info->attributes.by_reg = true;
|
||||
if (!platform_target.x86.is_mcu_api) info->attributes.by_reg = true;
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -516,8 +516,8 @@ static inline ABIArgInfo *x86_classify_aggregate(CallConvention call, Regs *regs
|
||||
// optimizations.
|
||||
// Don't do this for the MCU if there are still free integer registers
|
||||
// (see X86_64 ABI for full explanation).
|
||||
if (size <= 16 && (!build_target.x86.is_mcu_api || !regs->int_regs) &&
|
||||
x86_can_expand_indirect_aggregate_arg(type))
|
||||
if (size <= 16 && (!platform_target.x86.is_mcu_api || !regs->int_regs) &&
|
||||
x86_can_expand_indirect_aggregate_arg(type))
|
||||
{
|
||||
if (!needs_padding_in_reg) return abi_arg_new_expand();
|
||||
|
||||
@@ -626,11 +626,11 @@ void c_abi_func_create_x86(FunctionSignature *signature)
|
||||
{
|
||||
case CALL_CONVENTION_NORMAL:
|
||||
case CALL_CONVENTION_SYSCALL:
|
||||
if (build_target.x86.is_win32_float_struct_abi)
|
||||
if (platform_target.x86.is_win32_float_struct_abi)
|
||||
{
|
||||
regs.float_regs = 3;
|
||||
}
|
||||
regs.int_regs = build_target.default_number_regs;
|
||||
regs.int_regs = platform_target.default_number_regs;
|
||||
break;
|
||||
case CALL_CONVENTION_REGCALL:
|
||||
regs.int_regs = 5;
|
||||
@@ -646,7 +646,7 @@ void c_abi_func_create_x86(FunctionSignature *signature)
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (build_target.x86.is_mcu_api)
|
||||
if (platform_target.x86.is_mcu_api)
|
||||
{
|
||||
regs.float_regs = 0;
|
||||
regs.int_regs = 3;
|
||||
|
||||
@@ -111,10 +111,10 @@ void llvm_emit_debug_function(GenContext *c, Decl *decl)
|
||||
flags |= LLVMDIFlagPrototyped;
|
||||
if (decl->func.attr_noreturn) flags |= LLVMDIFlagNoReturn;
|
||||
|
||||
SourceLocation *loc = TOKILOC(decl->span.loc);
|
||||
SourceLocation *loc = TOKLOC(decl->span.loc);
|
||||
c->debug.function = LLVMDIBuilderCreateFunction(c->debug.builder,
|
||||
c->debug.file,
|
||||
decl->name, TOKILEN(decl->name_token),
|
||||
decl->name, TOKLEN(decl->name_token),
|
||||
decl->external_name, strlen(decl->external_name),
|
||||
c->debug.file,
|
||||
loc->line,
|
||||
|
||||
@@ -1657,7 +1657,7 @@ static inline LLVMValueRef llvm_fixup_shift_rhs(GenContext *c, LLVMValueRef left
|
||||
LLVMTypeRef left_type = LLVMTypeOf(left);
|
||||
LLVMTypeRef right_type = LLVMTypeOf(right);
|
||||
if (left_type == right_type) return right;
|
||||
if (LLVMStoreSizeOfType(build_target.target, left_type) < LLVMStoreSizeOfType(build_target.target, right_type))
|
||||
if (LLVMStoreSizeOfType(platform_target.target, left_type) < LLVMStoreSizeOfType(platform_target.target, right_type))
|
||||
{
|
||||
return LLVMBuildTrunc(c->builder, right, left_type, "");
|
||||
}
|
||||
|
||||
@@ -578,7 +578,7 @@ void llvm_emit_function_decl(GenContext *c, Decl *decl)
|
||||
}
|
||||
llvm_attribute_add(c, function, attribute_nounwind, -1);
|
||||
|
||||
if (decl->func.attr_stdcall && (build_target.os == OS_TYPE_WIN32))
|
||||
if (decl->func.attr_stdcall && (platform_target.os == OS_TYPE_WIN32))
|
||||
{
|
||||
LLVMSetFunctionCallConv(function, LLVMX86StdcallCallConv);
|
||||
LLVMSetDLLStorageClass(function, LLVMDLLImportStorageClass);
|
||||
|
||||
@@ -32,7 +32,7 @@ void gencontext_begin_module(GenContext *c)
|
||||
LLVMAddModuleFlag(c->module, LLVMModuleFlagBehaviorOverride, pie_level, strlen(pie_level), setting);
|
||||
}
|
||||
|
||||
LLVMSetTarget(c->module, build_target.target_triple);
|
||||
LLVMSetTarget(c->module, platform_target.target_triple);
|
||||
if (c->build_target->debug_info != DEBUG_INFO_NONE)
|
||||
{
|
||||
const char *filename = c->ast_context->file->name;
|
||||
|
||||
@@ -22,7 +22,7 @@ static bool context_next_is_type_with_path_prefix(Context *context)
|
||||
while (1)
|
||||
{
|
||||
current.index += 1;
|
||||
tok = TOKITYPE(current);
|
||||
tok = TOKTYPE(current);
|
||||
if (tok != TOKEN_COMMENT) break;
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ static bool context_next_is_type_with_path_prefix(Context *context)
|
||||
while (1)
|
||||
{
|
||||
current.index += 1;
|
||||
tok = TOKITYPE(current);
|
||||
tok = TOKTYPE(current);
|
||||
if (tok != TOKEN_COMMENT) break;
|
||||
}
|
||||
|
||||
@@ -816,7 +816,7 @@ static Decl *parse_const_declaration(Context *context, Visibility visibility)
|
||||
{
|
||||
decl->var.type_info = TRY_TYPE_OR(parse_type(context), poisoned_decl);
|
||||
}
|
||||
decl->name = TOKKSTR(context->tok);
|
||||
decl->name = TOKSTR(context->tok);
|
||||
decl->name_token = context->tok.id;
|
||||
if (!consume_const_name(context, "const")) return poisoned_decl;
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ static inline void parse_optional_label_target(Context *context, Label *label)
|
||||
if (TOKEN_IS(TOKEN_CONST_IDENT))
|
||||
{
|
||||
label->span = context->tok.id;
|
||||
label->name = TOKKSTR(context->tok);
|
||||
label->name = TOKSTR(context->tok);
|
||||
advance_and_verify(context, TOKEN_CONST_IDENT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,8 +44,8 @@ inline void advance(Context *context)
|
||||
// Handle doc comments
|
||||
if (context->next_tok.type == TOKEN_DOC_COMMENT)
|
||||
{
|
||||
SourceLocation *curr = TOKKLOC(context->tok);
|
||||
SourceLocation *next = TOKKLOC(context->next_tok);
|
||||
SourceLocation *curr = TOKLOC(context->tok);
|
||||
SourceLocation *next = TOKLOC(context->next_tok);
|
||||
vec_add(context->comments, context->next_tok);
|
||||
|
||||
if (curr->line == next->line)
|
||||
@@ -98,7 +98,7 @@ bool consume(Context *context, TokenType type, const char *message, ...)
|
||||
|
||||
va_list args;
|
||||
va_start(args, message);
|
||||
sema_verror_range(TOKKLOC(context->tok), message, args);
|
||||
sema_verror_range(TOKLOC(context->tok), message, args);
|
||||
va_end(args);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3181,7 +3181,7 @@ static Type *numeric_arithmetic_promotion(Type *type)
|
||||
{
|
||||
case ALL_SIGNED_INTS:
|
||||
case ALL_UNSIGNED_INTS:
|
||||
if (type->builtin.bitsize < build_target.width_c_int) return type_c_int->canonical;
|
||||
if (type->builtin.bitsize < platform_target.width_c_int) return type_c_int->canonical;
|
||||
return type;
|
||||
case TYPE_F16:
|
||||
// Promote F16 to a real type.
|
||||
|
||||
@@ -326,8 +326,8 @@ static inline bool sema_analyse_cond(Context *context, Expr *expr, bool cast_to_
|
||||
static inline bool sema_analyse_stmt_placement(Expr *cond, Ast *stmt)
|
||||
{
|
||||
if (stmt->ast_kind == AST_COMPOUND_STMT) return true;
|
||||
SourceLocation *end_of_cond = TOKILOC(cond->span.end_loc);
|
||||
SourceLocation *start_of_then = TOKILOC(stmt->span.loc);
|
||||
SourceLocation *end_of_cond = TOKLOC(cond->span.end_loc);
|
||||
SourceLocation *start_of_then = TOKLOC(stmt->span.loc);
|
||||
return end_of_cond->line == start_of_then->line;
|
||||
}
|
||||
|
||||
@@ -880,8 +880,8 @@ static inline bool sema_analyse_if_stmt(Context *context, Ast *statement)
|
||||
}
|
||||
if (success && statement->if_stmt.then_body->ast_kind != AST_COMPOUND_STMT)
|
||||
{
|
||||
SourceLocation *end_of_cond = TOKILOC(cond->span.end_loc);
|
||||
SourceLocation *start_of_then = TOKILOC(statement->if_stmt.then_body->span.loc);
|
||||
SourceLocation *end_of_cond = TOKLOC(cond->span.end_loc);
|
||||
SourceLocation *start_of_then = TOKLOC(statement->if_stmt.then_body->span.loc);
|
||||
if (end_of_cond->line != start_of_then->line)
|
||||
{
|
||||
SEMA_ERROR(statement->if_stmt.then_body,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -76,7 +76,6 @@ typedef enum
|
||||
OS_TYPE_UNKNOWN,
|
||||
OS_TYPE_ANANAS,
|
||||
OS_TYPE_CLOUD_ABI,
|
||||
OS_TYPE_DARWIN,
|
||||
OS_TYPE_DRAGON_FLY,
|
||||
OS_TYPE_FREE_BSD,
|
||||
OS_TYPE_FUCHSIA,
|
||||
@@ -141,11 +140,14 @@ typedef enum
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OBJ_FORMAT_UNSUPPORTED,
|
||||
OBJ_FORMAT_COFF,
|
||||
OBJ_FORMAT_GOFF,
|
||||
OBJ_FORMAT_ELF,
|
||||
OBJ_FORMAT_MACHO,
|
||||
OBJ_FORMAT_WASM,
|
||||
OBJ_FORMAT_XCOFF
|
||||
OBJ_FORMAT_XCOFF,
|
||||
OBJ_FORMAT_AOUT,
|
||||
} ObjectFormatType;
|
||||
|
||||
typedef enum
|
||||
@@ -291,13 +293,13 @@ typedef struct
|
||||
bool little_endian;
|
||||
bool tls_supported;
|
||||
bool asm_supported;
|
||||
bool float_128;
|
||||
bool float_16;
|
||||
bool vec_128i;
|
||||
bool vec_64i;
|
||||
bool vec_128f;
|
||||
bool vec_64f;
|
||||
bool int_128;
|
||||
bool float128;
|
||||
bool float16;
|
||||
bool vec128i;
|
||||
bool vec64i;
|
||||
bool vec128f;
|
||||
bool vec64f;
|
||||
bool int128;
|
||||
unsigned align_pref_pointer;
|
||||
unsigned align_pref_byte;
|
||||
unsigned align_pref_short;
|
||||
@@ -343,7 +345,7 @@ typedef struct
|
||||
unsigned max_size_for_return;
|
||||
char *platform_name;
|
||||
|
||||
} Target;
|
||||
} PlatformTarget;
|
||||
|
||||
|
||||
extern Target build_target;
|
||||
extern PlatformTarget platform_target;
|
||||
@@ -333,7 +333,7 @@ Type *type_abi_find_single_struct_element(Type *type)
|
||||
|
||||
static bool type_is_qpx_vector(Type *type)
|
||||
{
|
||||
if (build_target.abi != ABI_PPC64_SVR4 || !build_target.ppc64.has_qpx) return false;
|
||||
if (platform_target.abi != ABI_PPC64_SVR4 || !platform_target.ppc64.has_qpx) return false;
|
||||
type = type->canonical;
|
||||
if (type->type_kind != TYPE_VECTOR) return false;
|
||||
if (type->vector.len == 1) return false;
|
||||
@@ -389,17 +389,17 @@ bool type_is_abi_aggregate(Type *type)
|
||||
bool type_is_homogenous_base_type(Type *type)
|
||||
{
|
||||
type = type->canonical;
|
||||
switch (build_target.abi)
|
||||
switch (platform_target.abi)
|
||||
{
|
||||
case ABI_PPC64_SVR4:
|
||||
switch (type->type_kind)
|
||||
{
|
||||
case TYPE_F128:
|
||||
if (!build_target.float_128) return false;
|
||||
if (!platform_target.float128) return false;
|
||||
FALLTHROUGH;
|
||||
case TYPE_F32:
|
||||
case TYPE_F64:
|
||||
return !build_target.ppc64.is_softfp;
|
||||
return !platform_target.ppc64.is_softfp;
|
||||
case TYPE_VECTOR:
|
||||
return type_size(type) == 128 / 8 || type_is_qpx_vector(type);
|
||||
default:
|
||||
@@ -474,10 +474,10 @@ bool type_is_homogenous_base_type(Type *type)
|
||||
|
||||
bool type_homogenous_aggregate_small_enough(Type *type, unsigned members)
|
||||
{
|
||||
switch (build_target.abi)
|
||||
switch (platform_target.abi)
|
||||
{
|
||||
case ABI_PPC64_SVR4:
|
||||
if (type->type_kind == TYPE_F128 && build_target.float_128) return members <= 8;
|
||||
if (type->type_kind == TYPE_F128 && platform_target.float128) return members <= 8;
|
||||
if (type->type_kind == TYPE_VECTOR) return members <= 8;
|
||||
return ((type_size(type) + 7) / 8) * members <= 8;
|
||||
case ABI_X64:
|
||||
@@ -614,7 +614,7 @@ bool type_is_homogenous_aggregate(Type *type, Type **base, unsigned *elements)
|
||||
|
||||
AlignSize type_alloca_alignment(Type *type)
|
||||
{
|
||||
if (build_target.abi == ABI_X64)
|
||||
if (platform_target.abi == ABI_X64)
|
||||
{
|
||||
type = type_flatten(type);
|
||||
if (type->type_kind == TYPE_ARRAY && type_size(type) >= 16) return 16;
|
||||
@@ -1035,7 +1035,7 @@ static void type_create_alias(const char *name, Type *location, Type *canonical)
|
||||
}
|
||||
|
||||
|
||||
void builtin_setup(Target *target)
|
||||
void builtin_setup(PlatformTarget *target)
|
||||
{
|
||||
|
||||
/*TODO
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
#include "utils/lib.h"
|
||||
|
||||
static int version = 102;
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
// First setup memory
|
||||
memory_init();
|
||||
|
||||
|
||||
|
||||
DEBUG_LOG("Version: %d", version);
|
||||
|
||||
// Init the compiler
|
||||
|
||||
102
wrapper/src/wrapper.cpp
Normal file
102
wrapper/src/wrapper.cpp
Normal file
@@ -0,0 +1,102 @@
|
||||
|
||||
#include <llvm/ADT/ArrayRef.h>
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
|
||||
namespace lld {
|
||||
namespace coff {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
|
||||
namespace mingw {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
|
||||
namespace elf {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
|
||||
namespace mach_o {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
|
||||
namespace macho {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
|
||||
namespace wasm {
|
||||
bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
|
||||
llvm::raw_ostream &stdoutOS, llvm::raw_ostream &stderrOS);
|
||||
}
|
||||
}
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ELF,
|
||||
WASM,
|
||||
MACHO,
|
||||
COFF,
|
||||
MINGW
|
||||
} ObjFormat;
|
||||
|
||||
static bool llvm_link(ObjFormat format, const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
std::vector<const char*> arg_vector = std::vector<const char *>(arg_count + 1);
|
||||
for (int i = 0; i < arg_count; i++) arg_vector.push_back(args[i]);
|
||||
std::string output_string {};
|
||||
std::string output_err_string {};
|
||||
llvm::raw_string_ostream output { output_string };
|
||||
llvm::raw_string_ostream output_err { output_err_string };
|
||||
switch (format)
|
||||
{
|
||||
case ELF:
|
||||
if (lld::elf::link(arg_vector, false, output, output_err)) return true;
|
||||
break;
|
||||
case MACHO:
|
||||
if (lld::mach_o::link(arg_vector, false, output, output_err)) return true;
|
||||
break;
|
||||
case WASM:
|
||||
if (lld::wasm::link(arg_vector, false, output, output_err)) return true;
|
||||
break;
|
||||
case COFF:
|
||||
if (lld::coff::link(arg_vector, false, output, output_err)) return true;
|
||||
break;
|
||||
default:
|
||||
exit(-1);
|
||||
}
|
||||
*error_string = strdup(output_err_string.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
bool llvm_link_elf(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
return llvm_link(ELF, args, arg_count, error_string);
|
||||
}
|
||||
|
||||
bool llvm_link_macho(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
return llvm_link(MACHO, args, arg_count, error_string);
|
||||
}
|
||||
|
||||
bool llvm_link_coff(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
return llvm_link(COFF, args, arg_count, error_string);
|
||||
}
|
||||
|
||||
bool llvm_link_wasm(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
return llvm_link(WASM, args, arg_count, error_string);
|
||||
}
|
||||
|
||||
bool llvm_link_mingw(const char **args, int arg_count, const char** error_string)
|
||||
{
|
||||
return llvm_link(MINGW, args, arg_count, error_string);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user