mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
Do not link with debug libc on win32 when using cross compile libs. Add delete methods to dstring. Fixes to macOS aarch64 codegen. Use glibc backtrace when available. Add load_* methods to file. The cast (int[8])int_slice[:8] now works.
This commit is contained in:
committed by
Christoffer Lerno
parent
a50c5f4f7c
commit
1d61ace302
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -99,8 +99,8 @@ jobs:
|
||||
install: git binutils mingw-w64-x86_64-clang mingw-w64-x86_64-ninja mingw-w64-x86_64-cmake mingw-w64-x86_64-toolchain mingw-w64-x86_64-python
|
||||
- shell: msys2 {0}
|
||||
run: |
|
||||
pacman --noconfirm -U https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-llvm-17.0.4-1-any.pkg.tar.zst
|
||||
pacman --noconfirm -U https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-lld-17.0.4-1-any.pkg.tar.zst
|
||||
pacman --noconfirm -U https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-llvm-17.0.6-1-any.pkg.tar.zst
|
||||
pacman --noconfirm -U https://mirror.msys2.org/mingw/mingw64/mingw-w64-x86_64-lld-17.0.6-1-any.pkg.tar.zst
|
||||
- name: CMake
|
||||
run: |
|
||||
cmake -B build -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
|
||||
|
||||
@@ -280,6 +280,37 @@ fn void DString.append_char(&self, char c)
|
||||
data.chars[data.len++] = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* @require start < self.len()
|
||||
* @require end < self.len()
|
||||
* @require end >= start "End must be same or equal to the start"
|
||||
**/
|
||||
fn void DString.delete_range(&self, usz start, usz end)
|
||||
{
|
||||
self.delete(start, end - start + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @require start < self.len()
|
||||
* @require start + len <= self.len()
|
||||
**/
|
||||
fn void DString.delete(&self, usz start, usz len = 1)
|
||||
{
|
||||
if (!len) return;
|
||||
StringData* data = self.data();
|
||||
usz new_len = data.len - len;
|
||||
if (new_len == 0)
|
||||
{
|
||||
data.len = 0;
|
||||
return;
|
||||
}
|
||||
usz len_after = data.len - start - len;
|
||||
if (len_after > 0)
|
||||
{
|
||||
data.chars[start:len_after] = data.chars[start + len:len_after];
|
||||
}
|
||||
data.len = new_len;
|
||||
}
|
||||
|
||||
macro void DString.append(&self, value)
|
||||
{
|
||||
|
||||
@@ -444,6 +444,11 @@ fn String String.new_ascii_to_upper(s, Allocator* allocator = mem::heap())
|
||||
return copy;
|
||||
}
|
||||
|
||||
fn StringIterator String.iterator(s)
|
||||
{
|
||||
return { s, 0 };
|
||||
}
|
||||
|
||||
fn String String.temp_ascii_to_upper(s)
|
||||
{
|
||||
return s.new_ascii_to_upper(mem::temp());
|
||||
@@ -575,3 +580,38 @@ fn char! String.to_uchar(s) => s.to_integer(char);
|
||||
|
||||
fn double! String.to_double(s) => s.to_real(double);
|
||||
fn float! String.to_float(s) => s.to_real(float);
|
||||
|
||||
fn Splitter String.splitter(self, String split)
|
||||
{
|
||||
return Splitter { self, split, 0 };
|
||||
}
|
||||
|
||||
struct Splitter
|
||||
{
|
||||
String string;
|
||||
String split;
|
||||
usz current;
|
||||
}
|
||||
|
||||
fn void Splitter.reset(&self)
|
||||
{
|
||||
self.current = 0;
|
||||
}
|
||||
|
||||
fn String! Splitter.next(&self)
|
||||
{
|
||||
usz len = self.string.len;
|
||||
usz current = self.current;
|
||||
if (current >= len) return IteratorResult.NO_MORE_ELEMENT?;
|
||||
String remaining = self.string[current..];
|
||||
usz! next = remaining.index_of(self.split);
|
||||
if (try next)
|
||||
{
|
||||
defer self.current = current + next + self.split.len;
|
||||
return remaining[:next];
|
||||
}
|
||||
self.current = len;
|
||||
return remaining;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -20,4 +20,4 @@ fn Char32! StringIterator.next(&self)
|
||||
Char32 res = conv::utf8_to_char32(&self.utf8[current], &read)!;
|
||||
self.current += read;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,50 @@ fn char! File.read_byte(&self) @dynamic
|
||||
return (char)c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up to buffer.len characters. Returns IoError.OVERFLOW if the file is longer
|
||||
* than the buffer.
|
||||
*
|
||||
* @param filename "The path to the file to read"
|
||||
* @param [in] buffer "The buffer to read to"
|
||||
**/
|
||||
fn char[]! load_buffer(String filename, char[] buffer)
|
||||
{
|
||||
File file = open(filename, "rb")!;
|
||||
defer (void)file.close();
|
||||
usz len = file.seek(0, END)!;
|
||||
if (len > buffer.len) return IoError.OVERFLOW?;
|
||||
file.seek(0, SET)!;
|
||||
usz read = 0;
|
||||
while (read < len)
|
||||
{
|
||||
read += file.read(buffer[read:len - read])!;
|
||||
}
|
||||
return buffer[:len];
|
||||
|
||||
}
|
||||
|
||||
fn char[]! load_new(String filename, Allocator* allocator = mem::heap())
|
||||
{
|
||||
File file = open(filename, "rb")!;
|
||||
defer (void)file.close();
|
||||
usz len = file.seek(0, END)!;
|
||||
file.seek(0, SET)!;
|
||||
char* data = allocator.alloc_checked(len)!;
|
||||
defer catch allocator.free(data);
|
||||
usz read = 0;
|
||||
while (read < len)
|
||||
{
|
||||
read += file.read(data[read:len - read])!;
|
||||
}
|
||||
return data[:len];
|
||||
}
|
||||
|
||||
fn char[]! load_temp(String filename)
|
||||
{
|
||||
return load_new(filename, mem::temp());
|
||||
}
|
||||
|
||||
/**
|
||||
* @require self.file `File must be initialized`
|
||||
*/
|
||||
|
||||
@@ -49,7 +49,7 @@ fault IoError
|
||||
* @param stream
|
||||
* @require @is_instream(stream)
|
||||
**/
|
||||
macro String! readline(stream = io::stdin(), Allocator* allocator = mem::heap())
|
||||
macro String! readline(stream = io::stdin(), Allocator* allocator = mem::heap())
|
||||
{
|
||||
bool $is_stream = @typeid(stream) == InStream*.typeid;
|
||||
$if $is_stream:
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
module libc @if(env::POSIX);
|
||||
|
||||
|
||||
extern fn void* dlopen(ZString path, int flags);
|
||||
extern fn CInt dlclose(void*);
|
||||
extern fn void* dlsym(void* handle, ZString symbol);
|
||||
|
||||
const int RTLD_LAZY = 0x1;
|
||||
const int RTLD_NOW = 0x2;
|
||||
const int RTLD_LOCAL = 0x4;
|
||||
const int RTLD_GLOBAL = 0x8;
|
||||
|
||||
def Pid_t = int;
|
||||
def Uid_t = uint;
|
||||
def Gid_t = uint;
|
||||
|
||||
@@ -56,10 +56,21 @@ const CInt WNOHANG = 1;
|
||||
const CInt WUNTRACES = 2;
|
||||
|
||||
JmpBuf backtrace_jmpbuf @local;
|
||||
fn CInt backtrace(void** buffer, CInt size) @extern("backtrace") @weak
|
||||
def BacktraceFn = fn CInt(void** buffer, CInt size);
|
||||
|
||||
fn CInt backtrace(void** buffer, CInt size)
|
||||
{
|
||||
if (size < 1) return 0;
|
||||
|
||||
void* handle = libc::dlopen("libc.so.6", libc::RTLD_LAZY);
|
||||
if (handle)
|
||||
{
|
||||
BacktraceFn backtrace_fn = libc::dlsym(handle, "backtrace");
|
||||
libc::dlclose(handle);
|
||||
if (backtrace_fn)
|
||||
{
|
||||
return backtrace_fn(buffer, size);
|
||||
}
|
||||
}
|
||||
// Loop through the return addresses until we hit a signal.
|
||||
// This avoids using the frame address.
|
||||
SignalFunction restore_backtrace = fn void(CInt) {
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
# C3C Release Notes
|
||||
|
||||
## 0.5.1 Change list
|
||||
|
||||
### Changes / improvements
|
||||
- Improved error messages for const errors.
|
||||
- Do not link with debug libraries unless using static libraries.
|
||||
- Add 'print-linking' build option.
|
||||
- System linker may be used even if the target arch is different from current.
|
||||
- Slice -> array/vector works for constant slice lenghts.
|
||||
|
||||
### Fixes
|
||||
- On Aarch64 use the correct frame pointer type.
|
||||
- On Aarch64 macOS, ensure the minimum version is 11.0 (Big Sur)
|
||||
- Fixes to the yacc grammar.
|
||||
- Dsym generation on macOS will correctly emit -arch.
|
||||
- Stacktrace on signals on Linux when backtrace is available.
|
||||
|
||||
### Stdlib changes
|
||||
- `delete` and `delete_range` added to DString.
|
||||
- `Splitter` iterator added.
|
||||
- `splitter` and `iterator` String methods.
|
||||
- `load_new`, `load_buffer` and `load_temp` std::io::file functions.
|
||||
|
||||
## 0.5.0 Change List
|
||||
|
||||
### Changes / improvements
|
||||
|
||||
@@ -379,6 +379,7 @@ typedef struct BuildOptions_
|
||||
bool print_project_properties;
|
||||
bool print_precedence;
|
||||
bool print_build_settings;
|
||||
bool print_linking;
|
||||
bool benchmarking;
|
||||
bool testing;
|
||||
} BuildOptions;
|
||||
@@ -450,6 +451,7 @@ typedef struct
|
||||
bool testing;
|
||||
bool read_stdin;
|
||||
bool print_output;
|
||||
bool print_linking;
|
||||
bool no_entry;
|
||||
int build_threads;
|
||||
TrustLevel trust_level;
|
||||
|
||||
@@ -123,6 +123,7 @@ static void usage(void)
|
||||
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(" --system-linker=<yes|no> - Use the system linker (default: no for cross compilation, yes otherwise).");
|
||||
OUTPUT(" --cc <path> - Set C compiler (for C files in projects and use as system linker).");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --use-stdlib=<yes|no> - Include the standard library (default: yes).");
|
||||
OUTPUT(" --link-libc=<yes|no> - Link libc other default libraries (default: yes).");
|
||||
@@ -140,6 +141,7 @@ static void usage(void)
|
||||
OUTPUT(" --fp-math=<option> - FP math behaviour: strict, relaxed, fast.");
|
||||
OUTPUT("");
|
||||
OUTPUT(" --debug-stats - Print debug statistics.");
|
||||
OUTPUT(" --print-linking - Print linker arguments.");
|
||||
#ifndef NDEBUG
|
||||
OUTPUT(" --debug-log - Print debug logging to stdout.");
|
||||
#endif
|
||||
@@ -747,6 +749,11 @@ static void parse_option(BuildOptions *options)
|
||||
debug_stats = true;
|
||||
return;
|
||||
}
|
||||
if (match_longopt("print-linking"))
|
||||
{
|
||||
options->print_linking = true;
|
||||
return;
|
||||
}
|
||||
if (match_longopt("list-keywords"))
|
||||
{
|
||||
options->print_keywords = true;
|
||||
|
||||
@@ -252,6 +252,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
|
||||
{
|
||||
target->arch_os_target = options->arch_os_target_override;
|
||||
}
|
||||
target->print_linking = options->print_linking;
|
||||
if (options->reloc_model != RELOC_DEFAULT) target->reloc_model = options->reloc_model;
|
||||
|
||||
if (options->symtab_size) target->symtab_size = options->symtab_size;
|
||||
|
||||
@@ -490,8 +490,25 @@ void compiler_compile(void)
|
||||
{
|
||||
error_exit("Cannot create exe with the name '%s' - there is already a directory with that name.", output_exe);
|
||||
}
|
||||
if (link_libc() && platform_target.os != OS_TYPE_WIN32
|
||||
&& active_target.arch_os_target == default_target && active_target.system_linker != SYSTEM_LINKER_OFF)
|
||||
bool system_linker_available = link_libc() && platform_target.os != OS_TYPE_WIN32;
|
||||
bool use_system_linker = system_linker_available && active_target.arch_os_target == default_target;
|
||||
switch (active_target.system_linker)
|
||||
{
|
||||
case SYSTEM_LINKER_ON:
|
||||
if (!system_linker_available)
|
||||
{
|
||||
eprintf("System linker is not supported, defaulting to built-in linker\n");
|
||||
break;
|
||||
}
|
||||
use_system_linker = true;
|
||||
break;
|
||||
case SYSTEM_LINKER_OFF:
|
||||
use_system_linker = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (use_system_linker)
|
||||
{
|
||||
platform_linker(output_exe, obj_files, output_file_count);
|
||||
compiler_link_time = bench_mark();
|
||||
@@ -504,7 +521,7 @@ void compiler_compile(void)
|
||||
if (!obj_format_linking_supported(platform_target.object_format) || !linker(output_exe, obj_files,
|
||||
output_file_count))
|
||||
{
|
||||
printf("No linking is performed due to missing linker support.\n");
|
||||
eprintf("No linking is performed due to missing linker support.\n");
|
||||
active_target.run_after_compile = false;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -113,6 +113,7 @@ typedef enum
|
||||
CAST_SABOOL,
|
||||
CAST_SAPTR,
|
||||
CAST_SASA,
|
||||
CAST_SAARR,
|
||||
CAST_STRPTR,
|
||||
CAST_STINLINE,
|
||||
CAST_VECARR,
|
||||
|
||||
@@ -380,8 +380,10 @@ static inline bool expr_cast_is_constant_eval(Expr *expr, ConstantEvalKind eval_
|
||||
case CAST_IDINT:
|
||||
case CAST_INTARRBS:
|
||||
case CAST_BSINTARR:
|
||||
case CAST_SAARR:
|
||||
if (eval_kind == CONSTANT_EVAL_CONSTANT_VALUE) return false;
|
||||
return exprid_is_constant_eval(expr->cast_expr.expr, eval_kind);
|
||||
|
||||
}
|
||||
UNREACHABLE
|
||||
}
|
||||
|
||||
@@ -98,6 +98,12 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type,
|
||||
UNREACHABLE
|
||||
}
|
||||
if (!link_libc()) return;
|
||||
bool link_with_dynamic_debug_libc = true;
|
||||
#if !PLATFORM_WINDOWS
|
||||
// The debug version of libc is usually not available on target machines,
|
||||
// so we do not link with debug dll versions of libc.
|
||||
link_with_dynamic_debug_libc = false;
|
||||
#endif
|
||||
if (!active_target.win.sdk)
|
||||
{
|
||||
const char *path = windows_cross_compile_library();
|
||||
@@ -123,6 +129,9 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type,
|
||||
if (file_exists(scratch_buffer_to_string()))
|
||||
{
|
||||
active_target.win.sdk = scratch_buffer_copy();
|
||||
// If we only use the msvc cross compile on windows, we
|
||||
// avoid linking with dynamic debug dlls.
|
||||
link_with_dynamic_debug_libc = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -171,7 +180,9 @@ static void linker_setup_windows(const char ***args_ref, LinkerType linker_type,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_debug)
|
||||
// When cross compiling we might not have the relevant debug libraries.
|
||||
// if so, then exclude them.
|
||||
if (is_debug && link_with_dynamic_debug_libc)
|
||||
{
|
||||
vec_add(*additional_linked_ref, "ucrtd");
|
||||
vec_add(*additional_linked_ref, "vcruntimed");
|
||||
@@ -284,6 +295,8 @@ static void linker_setup_macos(const char ***args_ref, LinkerType linker_type)
|
||||
add_arg("CoreFoundation");
|
||||
if (linker_type == LINKER_CC)
|
||||
{
|
||||
add_arg("-target");
|
||||
add_arg(platform_target.target_triple);
|
||||
return;
|
||||
}
|
||||
add_arg("-arch");
|
||||
@@ -774,6 +787,7 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
|
||||
vec_add(parts, "-lm");
|
||||
}
|
||||
const char *output = concat_string_parts(parts);
|
||||
if (active_target.print_linking) puts(output);
|
||||
if (system(output) != 0)
|
||||
{
|
||||
error_exit("Failed to link executable '%s' using command '%s'.\n", output_file, output);
|
||||
@@ -782,7 +796,8 @@ void platform_linker(const char *output_file, const char **files, unsigned file_
|
||||
{
|
||||
// Create .dSYM
|
||||
scratch_buffer_clear();
|
||||
scratch_buffer_printf("dsymutil %s", output_file);
|
||||
scratch_buffer_printf("dsymutil -arch %s %s", arch_to_linker_arch(platform_target.arch), output_file);
|
||||
if (active_target.print_linking) puts(scratch_buffer_to_string());
|
||||
if (system(scratch_buffer_to_string()) != 0)
|
||||
{
|
||||
puts("Failed to create .dSYM files, debugging will be impacted.");
|
||||
|
||||
@@ -1067,7 +1067,7 @@ void llvm_append_function_attributes(GenContext *c, Decl *decl)
|
||||
llvm_set_alignment(function, decl->alignment);
|
||||
}
|
||||
llvm_attribute_add(c, function, attribute_id.nounwind, -1);
|
||||
llvm_attribute_add_int(c, function, attribute_id.uwtable, 2, -1);
|
||||
llvm_attribute_add_int(c, function, attribute_id.uwtable, UWTABLE, -1);
|
||||
|
||||
if (decl->func_decl.attr_naked)
|
||||
{
|
||||
|
||||
@@ -1236,6 +1236,22 @@ void llvm_emit_array_to_vector_cast(GenContext *c, BEValue *value, Type *to_type
|
||||
}
|
||||
|
||||
|
||||
void llvm_emit_subarray_to_vec_array_cast(GenContext *c, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
BEValue pointer;
|
||||
Type *base = type_lowering(from_type)->array.base;
|
||||
AlignSize element_alignment = type_abi_alignment(base);
|
||||
llvm_emit_subarray_pointer(c, value, &pointer);
|
||||
llvm_value_rvalue(c, &pointer);
|
||||
LLVMTypeRef type = llvm_get_type(c, to_type);
|
||||
AlignSize alignment = llvm_abi_alignment(c, type);
|
||||
LLVMValueRef temp = llvm_emit_alloca(c, type, alignment, ".temp");
|
||||
unsigned elements = LLVMGetTypeKind(type) == LLVMVectorTypeKind
|
||||
? LLVMGetVectorSize(type) : LLVMGetArrayLength(type);
|
||||
llvm_emit_memcpy(c, temp, alignment, pointer.value, element_alignment, elements);
|
||||
llvm_value_set_address(value, temp, to_type, alignment);
|
||||
}
|
||||
|
||||
void llvm_emit_expand_to_vec_cast(GenContext *c, BEValue *value, Type *to_type, Type *from_type)
|
||||
{
|
||||
llvm_value_rvalue(c, value);
|
||||
@@ -1356,6 +1372,9 @@ void llvm_emit_cast(GenContext *c, CastKind cast_kind, Expr *expr, BEValue *valu
|
||||
|
||||
switch (cast_kind)
|
||||
{
|
||||
case CAST_SAARR:
|
||||
llvm_emit_subarray_to_vec_array_cast(c, value, to_type, from_type);
|
||||
return;
|
||||
case CAST_EXPVEC:
|
||||
llvm_emit_expand_to_vec_cast(c, value, to_type, from_type);
|
||||
return;
|
||||
|
||||
@@ -522,6 +522,8 @@ void llvm_emit_debug_parameter(GenContext *c, Decl *parameter, unsigned index);
|
||||
void llvm_emit_debug_local_var(GenContext *c, Decl *var);
|
||||
void llvm_emit_debug_global_var(GenContext *c, Decl *global);
|
||||
|
||||
#define FRAMEPOINTER (platform_target.arch == ARCH_TYPE_AARCH64 ? 1 : 2)
|
||||
#define UWTABLE (active_target.arch_os_target == MACOS_AARCH64 ? 1 : 2)
|
||||
#define EMIT_LOC(c, x) do { if (c->debug.builder) llvm_emit_debug_location(c, x->span); } while (0)
|
||||
#define EMIT_SPAN(c, x) do { if (c->debug.builder) llvm_emit_debug_location(c, x); } while (0)
|
||||
|
||||
|
||||
@@ -152,9 +152,9 @@ void gencontext_begin_module(GenContext *c)
|
||||
{
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorWarning, "Dwarf Version", 4, type_uint);
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorWarning, "Debug Info Version", 3, type_uint);
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorWarning, "frame-pointer", 2, type_uint);
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorWarning, "frame-pointer", FRAMEPOINTER, type_uint);
|
||||
}
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorError, "uwtable", 2, type_uint);
|
||||
llvm_set_module_flag(c, LLVMModuleFlagBehaviorError, "uwtable", UWTABLE, type_uint);
|
||||
|
||||
c->debug.runtime_version = 1;
|
||||
c->debug.builder = LLVMCreateDIBuilder(c->module);
|
||||
|
||||
@@ -1859,10 +1859,24 @@ static void cast_sa_to_vecarr(SemaContext *context, Expr *expr, Type *to_type)
|
||||
{
|
||||
if (!expr_is_const(expr))
|
||||
{
|
||||
switch (expr->expr_kind)
|
||||
{
|
||||
case EXPR_CAST:
|
||||
{
|
||||
Expr *inner = exprptr(expr->cast_expr.expr)->unary_expr.expr;
|
||||
expr_replace(expr, inner);
|
||||
cast_no_check(context, expr, to_type, false);
|
||||
return;
|
||||
}
|
||||
case EXPR_SLICE:
|
||||
{
|
||||
insert_runtime_cast(expr, CAST_SAARR, to_type);
|
||||
return;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
assert(expr->expr_kind == EXPR_CAST);
|
||||
Expr *inner = exprptr(expr->cast_expr.expr)->unary_expr.expr;
|
||||
expr_replace(expr, inner);
|
||||
cast_no_check(context, expr, to_type, false);
|
||||
return;
|
||||
}
|
||||
assert(expr_is_const(expr));
|
||||
|
||||
@@ -4484,12 +4484,12 @@ static inline IndexDiff range_const_len(Range *range)
|
||||
{
|
||||
Expr *start = exprptr(range->start);
|
||||
Expr *end = exprptrzero(range->end);
|
||||
if (!expr_is_const_int(start)) return -1;
|
||||
if (!end || !expr_is_const_int(end)) return -1;
|
||||
if (!int_fits(end->const_expr.ixx, TYPE_I32)) return -1;
|
||||
if (!int_fits(start->const_expr.ixx, TYPE_I32)) return -1;
|
||||
IndexDiff end_val = (IndexDiff)int_to_i64(end->const_expr.ixx);
|
||||
if (range->is_len) return end_val;
|
||||
if (!expr_is_const_int(start)) return -1;
|
||||
if (!int_fits(start->const_expr.ixx, TYPE_I32)) return -1;
|
||||
IndexDiff start_val = (IndexDiff)int_to_i64(start->const_expr.ixx);
|
||||
if (range->start_from_end && range->end_from_end) return start_val - end_val + 1;
|
||||
if (range->start_from_end != range->end_from_end) return -1;
|
||||
@@ -8387,7 +8387,11 @@ MemberIndex sema_len_from_const(Expr *expr)
|
||||
// We also handle the case where we have a cast from a const array.
|
||||
if (!expr_is_const(expr))
|
||||
{
|
||||
if (expr->type->type_kind != TYPE_SUBARRAY) return -1;
|
||||
if (type_flatten(expr->type)->type_kind != TYPE_SUBARRAY) return -1;
|
||||
if (expr->expr_kind == EXPR_SLICE)
|
||||
{
|
||||
return range_const_len(&expr->subscript_expr.range);
|
||||
}
|
||||
if (expr->expr_kind != EXPR_CAST) return -1;
|
||||
if (expr->cast_expr.kind != CAST_APTSA) return -1;
|
||||
Expr *inner = exprptr(expr->cast_expr.expr);
|
||||
|
||||
@@ -1948,6 +1948,17 @@ void target_setup(BuildTarget *target)
|
||||
{
|
||||
DEBUG_LOG("Macos SDK: %s", sysroot);
|
||||
active_target.macos.sdk = macos_sysroot_sdk_information(sysroot);
|
||||
if (platform_target.arch == ARCH_TYPE_AARCH64)
|
||||
{
|
||||
if (active_target.macos.sdk->macos_min_deploy_target.major < 11)
|
||||
{
|
||||
active_target.macos.sdk->macos_min_deploy_target = (Version) { 11, 0 };
|
||||
}
|
||||
if (active_target.macos.sdk->macos_deploy_target.major < 11)
|
||||
{
|
||||
active_target.macos.sdk->macos_deploy_target = (Version) { 11, 0 };
|
||||
}
|
||||
}
|
||||
}
|
||||
platform_target.target_triple = strdup(llvm_macos_target_triple(platform_target.target_triple));
|
||||
|
||||
|
||||
17
test/unit/regression/cast_slice_to_arr.c3
Normal file
17
test/unit/regression/cast_slice_to_arr.c3
Normal file
@@ -0,0 +1,17 @@
|
||||
module slice_to_arr @test;
|
||||
|
||||
fn void to_arr()
|
||||
{
|
||||
int[] x = { 1, 2, 3, 4, 5 };
|
||||
int z = 2;
|
||||
int[2] y = x[z:2];
|
||||
assert(y == int[2]{ 3, 4 });
|
||||
}
|
||||
|
||||
fn void to_vec()
|
||||
{
|
||||
int[] x = { 1, 2, 3, 4, 5 };
|
||||
int z = 2;
|
||||
int[<2>] y = x[z:2];
|
||||
assert(y == { 3, 4 });
|
||||
}
|
||||
@@ -2,6 +2,28 @@ module std::core::dstring2 @test;
|
||||
|
||||
const TEST_STRING = "hello world";
|
||||
|
||||
fn void test_delete()
|
||||
{
|
||||
{
|
||||
DString d;
|
||||
d.append("Hello cruel world.");
|
||||
d.delete_range(5, 10);
|
||||
assert(d.str_view() == "Hello world.");
|
||||
}
|
||||
DString d;
|
||||
d.append("Hello cruel world.");
|
||||
d.delete(0, 2);
|
||||
assert(d.str_view() == "llo cruel world.");
|
||||
d.delete(14, 2);
|
||||
assert(d.str_view() == "llo cruel worl");
|
||||
d.delete(7);
|
||||
assert(d.str_view() == "llo crul worl");
|
||||
d.delete(2, 0);
|
||||
assert(d.str_view() == "llo crul worl");
|
||||
d.delete(0, 1);
|
||||
assert(d.str_view() == "lo crul worl");
|
||||
}
|
||||
|
||||
fn void test_append()
|
||||
{
|
||||
DString str = dstring::new(TEST_STRING);
|
||||
|
||||
Reference in New Issue
Block a user