Limit vector max size, default is 4096 bits, but may be increased using --max-vector-size.

This commit is contained in:
Christoffer Lerno
2025-05-23 21:40:14 +02:00
parent c2c0ecded8
commit b5ddc36d7f
12 changed files with 68 additions and 13 deletions

View File

@@ -120,6 +120,7 @@ const String COMPILER_BUILD_HASH = $$BUILD_HASH;
const String COMPILER_BUILD_DATE = $$BUILD_DATE;
const OsType OS_TYPE = OsType.from_ordinal($$OS_TYPE);
const ArchType ARCH_TYPE = ArchType.from_ordinal($$ARCH_TYPE);
const usz MAX_VECTOR_SIZE = $$MAX_VECTOR_SIZE;
const bool ARCH_32_BIT = $$REGISTER_SIZE == 32;
const bool ARCH_64_BIT = $$REGISTER_SIZE == 64;
const bool LIBC = $$COMPILER_LIBC_AVAILABLE;

View File

@@ -14,6 +14,7 @@
- Deprecate `MyEnum.elements`.
- Deprecate `SomeFn.params`.
- Improve error message when encountering recursively defined structs. #2146
- Limit vector max size, default is 4096 bits, but may be increased using --max-vector-size.
### Fixes
- Assert triggered when casting from `int[2]` to `uint[2]` #2115

View File

@@ -7,6 +7,7 @@
#include "../version.h"
#include <stdint.h>
#define MAX_SYMTAB_SIZE (1024 * 1024)
#define MAX_BUILD_LIB_DIRS 1024
#define MAX_COMMAND_LINE_FILES 4096
#define MAX_COMMAND_LINE_RUN_ARGS 2048
@@ -578,6 +579,7 @@ typedef struct BuildOptions_
RiscvFloatCapability riscv_float_capability;
MemoryEnvironment memory_environment;
SanitizeMode sanitize_mode;
uint32_t max_vector_size;
bool print_keywords;
bool print_attributes;
bool print_builtins;
@@ -702,6 +704,7 @@ typedef struct
CompilerBackend backend;
LinkerType linker_type;
uint32_t symtab_size;
uint32_t max_vector_size;
uint32_t switchrange_max_size;
uint32_t switchjump_max_size;
const char **args;

View File

@@ -168,6 +168,7 @@ static void usage(bool full)
print_opt("--fp-math=<option>", "FP math behaviour: strict, relaxed, fast.");
print_opt("--win64-simd=<option>", "Win64 SIMD ABI: array, full.");
print_opt("--win-debug=<option>", "Select debug output on Windows: codeview or dwarf (default: codeview).");
print_opt("--max-vector-size <number>", "Set the maximum vector bit size to allow (default: 4096).");
PRINTF("");
print_opt("--print-linking", "Print linker arguments.");
PRINTF("");
@@ -771,7 +772,11 @@ static void parse_option(BuildOptions *options)
if (at_end() || next_is_opt()) error_exit("error: --symtab needs a valid integer.");
const char *symtab_string = next_arg();
int symtab = atoi(symtab_string);
if (symtab < 1024) PRINTF("Expected a valid positive integer >= 1024.");
if (symtab < 1024) error_exit("Expected the --symtab size to be valid positive integer >= 1024.");
if (symtab > MAX_SYMTAB_SIZE)
{
error_exit("The symtab size is too large. The maximum size is %d.", (int)MAX_SYMTAB_SIZE);
}
options->symtab_size = next_highest_power_of_2(symtab);
return;
}
@@ -887,6 +892,17 @@ static void parse_option(BuildOptions *options)
options->riscv_float_capability = parse_opt_select(RiscvFloatCapability, argopt, riscv_capability);
return;
}
if ((argopt = match_argopt("max-vector-size")))
{
int size = atoi(next_arg());
if (size < 128) error_exit("Expected a valid positive integer >= 128 or --max-vector-size.");
if (size > MAX_VECTOR_WIDTH) error_exit("Expected a valid positive integer <= %u for --max-vector-size.", (unsigned)MAX_VECTOR_WIDTH);
if (size != next_highest_power_of_2(size))
{
error_exit("The --max-vector-size value must be a power of 2, try using %u instead.", next_highest_power_of_2(size));
}
return;
}
if ((argopt = match_argopt("memory-env")))
{
options->memory_environment = parse_opt_select(MemoryEnvironment, argopt, memory_environment);

View File

@@ -403,6 +403,7 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
OVERRIDE_IF_SET(testfn);
OVERRIDE_IF_SET(benchfn);
OVERRIDE_IF_SET(symtab_size);
OVERRIDE_IF_SET(max_vector_size);
OVERRIDE_IF_SET(win.def);
OVERRIDE_IF_SET(no_entry);
@@ -416,6 +417,8 @@ static void update_build_target_from_options(BuildTarget *target, BuildOptions *
OVERRIDE_IF_SET(android.ndk_path);
OVERRIDE_IF_SET(android.api_version);
if (!target->max_vector_size) target->max_vector_size = DEFAULT_VECTOR_WIDTH;
if (options->silence_deprecation || options->verbosity_level < 0) target->silence_deprecation = options->silence_deprecation || options->verbosity_level < 0;
target->print_linking = options->print_linking || options->verbosity_level > 1;

View File

@@ -143,7 +143,6 @@ const char* project_target_keys[][2] = {
const int project_target_keys_count = ELEMENTLEN(project_target_keys);
const int project_deprecated_target_keys_count = ELEMENTLEN(project_deprecated_target_keys);
#define MAX_SYMTAB_SIZE (1024 * 1024)
#define GET_SETTING(type__, key__, strings__, comment__) \
(type__)get_valid_string_setting(context, json, key__, strings__, 0, ELEMENTLEN(strings__), comment__)
@@ -276,6 +275,21 @@ static void load_into_build_target(BuildParseContext context, JSONObject *json,
target->symtab_size = (uint32_t)symtab_size;
}
// Vector size
long vector_size = get_valid_integer(context, json, "max-vector-size", false);
if (vector_size > 0)
{
if (vector_size < 128)
{
error_exit("Error reading %s: max vector size was less than 128.", context.file);
}
if (vector_size > MAX_VECTOR_WIDTH)
{
error_exit("Error reading %s: max vector width may not exceed %d.", context.file, MAX_VECTOR_WIDTH);
}
target->max_vector_size = (uint32_t)vector_size;
}
// Target
const char *arch_os_string = get_optional_string(context, json, "target");
if (arch_os_string)

View File

@@ -1456,6 +1456,7 @@ void compile()
setup_int_define("C_LONG_SIZE", compiler.platform.width_c_long, type_int);
setup_int_define("C_LONG_LONG_SIZE", compiler.platform.width_c_long_long, type_int);
setup_int_define("REGISTER_SIZE", compiler.platform.width_register, type_int);
setup_int_define("MAX_VECTOR_SIZE", compiler.build.max_vector_size, type_int);
setup_bool_define("C_CHAR_IS_SIGNED", compiler.platform.signed_c_char);
setup_bool_define("PLATFORM_BIG_ENDIAN", compiler.platform.big_endian);
setup_bool_define("PLATFORM_I128_SUPPORTED", compiler.platform.int128);

View File

@@ -81,11 +81,11 @@ bool sema_resolve_array_like_len(SemaContext *context, TypeInfo *type_info, Arra
}
// Check max values.
if (int_icomp(len, is_vector ? MAX_VECTOR_WIDTH : MAX_ARRAY_SIZE, BINARYOP_GT))
if (int_icomp(len, is_vector ? compiler.build.max_vector_size / 8 : MAX_ARRAY_SIZE, BINARYOP_GT))
{
if (is_vector)
{
SEMA_ERROR(len_expr, "A vector may not exceed %d in width.", MAX_VECTOR_WIDTH);
SEMA_ERROR(len_expr, "A vector may not exceed %d in bit width.", compiler.build.max_vector_size);
}
else
{
@@ -190,6 +190,15 @@ static inline bool sema_resolve_array_type(SemaContext *context, TypeInfo *type,
if (!sema_check_array_type(context, type, type->array.base->type, kind, len, &type->type)) return type_info_poison(type);
ASSERT(!type->array.len || sema_cast_const(type->array.len));
type->resolve_status = RESOLVE_DONE;
if (kind == TYPE_INFO_VECTOR)
{
if (kind == TYPE_INFO_VECTOR && type_size(type->type) > compiler.build.max_vector_size / 8)
{
RETURN_SEMA_ERROR(type, "Vectors with bitsize over %u are not supported (this vector is %llu bits), "
"but you can increase the maximum allowed using '--max-vector-size'.",
compiler.build.max_vector_size, (unsigned long long)type_size(type->type) * 8);
}
}
return true;
}

View File

@@ -22,6 +22,7 @@
#define NO_ARENA 0
#define MAX_VECTOR_WIDTH 65536
#define DEFAULT_VECTOR_WIDTH 4096
#define MAX_ARRAY_SIZE INT64_MAX
#define MAX_SOURCE_LOCATION_LEN 255
#define PROJECT_JSON "project.json"

View File

@@ -0,0 +1,5 @@
fn void main()
{
double[<65>] x; // #error: Vectors with bitsize over
$echo $sizeof(x) * 8;
}

View File

@@ -81,16 +81,16 @@ fn void test_hash()
(uint[<100>]){}.hash();
(uint[100]){}.hash();
(long){}.hash();
(long[<100>]){}.hash();
(long[<20>]){}.hash();
(long[100]){}.hash();
(ulong){}.hash();
(ulong[<100>]){}.hash();
(ulong[<20>]){}.hash();
(ulong[100]){}.hash();
(int128){}.hash();
(int128[<100>]){}.hash();
(int128[<20>]){}.hash();
(int128[100]){}.hash();
(uint128){}.hash();
(uint128[<100>]){}.hash();
(uint128[<20>]){}.hash();
(uint128[100]){}.hash();
(bool){}.hash();
(bool[<100>]){}.hash();
@@ -122,16 +122,16 @@ fn void test_hash_repeat()
assert((uint[<100>]){}.hash() == (uint[<100>]){}.hash());
assert((uint[100]){}.hash() == (uint[100]){}.hash());
assert((long){}.hash() == (long){}.hash());
assert((long[<100>]){}.hash() == (long[<100>]){}.hash());
assert((long[<20>]){}.hash() == (long[<20>]){}.hash());
assert((long[100]){}.hash() == (long[100]){}.hash());
assert((ulong){}.hash() == (ulong){}.hash());
assert((ulong[<100>]){}.hash() == (ulong[<100>]){}.hash());
assert((ulong[<20>]){}.hash() == (ulong[<20>]){}.hash());
assert((ulong[100]){}.hash() == (ulong[100]){}.hash());
assert((int128){}.hash() == (int128){}.hash());
assert((int128[<100>]){}.hash() == (int128[<100>]){}.hash());
assert((int128[<20>]){}.hash() == (int128[<20>]){}.hash());
assert((int128[100]){}.hash() == (int128[100]){}.hash());
assert((uint128){}.hash() == (uint128){}.hash());
assert((uint128[<100>]){}.hash() == (uint128[<100>]){}.hash());
assert((uint128[<20>]){}.hash() == (uint128[<20>]){}.hash());
assert((uint128[100]){}.hash() == (uint128[100]){}.hash());
assert((bool){}.hash() == (bool){}.hash());
assert((bool[<100>]){}.hash() == (bool[<100>]){}.hash());

View File

@@ -1,4 +1,5 @@
module std::os::process @test;
// Currently disabled as they somewhat mess up the test output.
module std::os::process @test @if(false);
import std::os, std::io;
fn void test_inherit_stdio_stdout()