From 232632b74eacd2c79cc7f239870fa12494de1b37 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 18 Aug 2021 20:07:38 +0200 Subject: [PATCH] Add section with (incomplete) checking for mach-o --- src/compiler/llvm_codegen.c | 4 ++ src/compiler/sema_decls.c | 48 ++++++++++++++++--- src/utils/lib.h | 1 + src/utils/stringutils.c | 17 +++++++ test/src/tester.py | 2 + .../abi/macho_section_attributes.c3 | 8 ++++ 6 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 test/test_suite/abi/macho_section_attributes.c3 diff --git a/src/compiler/llvm_codegen.c b/src/compiler/llvm_codegen.c index ffc521a39..5495dab19 100644 --- a/src/compiler/llvm_codegen.c +++ b/src/compiler/llvm_codegen.c @@ -362,6 +362,10 @@ void llvm_emit_global_variable_init(GenContext *c, Decl *decl) // TODO fix name LLVMValueRef old = decl->backend_ref; decl->backend_ref = LLVMAddGlobal(c->module, LLVMTypeOf(init_value), decl->extname ?: decl->external_name); + if (decl->section) + { + LLVMSetSection(decl->backend_ref, decl->section); + } llvm_set_alignment(decl->backend_ref, alignment); LLVMValueRef failable_ref = decl->var.failable_ref; diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index ee590ba88..19f3099ef 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -9,6 +9,46 @@ static bool sema_analyse_struct_union(Context *context, Decl *decl); +static bool sema_check_section(Context *context, Decl *decl, Attr *attr) +{ + const char *section_string = attr->expr->const_expr.string.chars; + decl->section = section_string; + // No restrictions except for MACH-O + if (platform_target.object_format != OBJ_FORMAT_MACHO) + { + return true; + } + scratch_buffer_clear(); + StringSlice slice = strtoslice(section_string); + StringSlice segment = strnexttok(&slice, ','); + StringSlice section = strnexttok(&slice, ','); + StringSlice attrs = strnexttok(&slice, ','); + StringSlice stub_size_str = strnexttok(&slice, ','); + + if (slice.len) + { + SEMA_ERROR(attr->expr, "Too many parts to the Mach-o section description."); + } + slicetrim(&segment); + if (segment.len == 0) + { + SEMA_ERROR(attr->expr, "The segment is missing, did you type it correctly?"); + return false; + } + slicetrim(§ion); + if (section.len == 0) + { + SEMA_ERROR(attr->expr, "Mach-o requires 'segment,section' as the format, did you type it correctly?"); + return false; + } + if (section.len > 16) + { + SEMA_ERROR(attr->expr, "Mach-o requires the section to be at the most 16 characters, can you shorten it?"); + return false; + } + // TODO improve checking + return true; +} static bool sema_check_unique_parameters(Decl **decls) { STable *table = &global_context.scratch_table; @@ -300,10 +340,6 @@ static bool sema_analyse_struct_union(Context *context, Decl *decl) had = decl->extname != NULL; decl->extname = attr->expr->const_expr.string.chars; break; - case ATTRIBUTE_SECTION: - had = decl->section != NULL; - decl->section = attr->expr->const_expr.string.chars; - break; case ATTRIBUTE_ALIGN: had = decl->alignment != 0; decl->alignment = attr->alignment; @@ -994,7 +1030,7 @@ static inline bool sema_analyse_func(Context *context, Decl *decl) break; case ATTRIBUTE_SECTION: had = decl->section != NULL; - decl->section = attr->expr->const_expr.string.chars; + if (!sema_check_section(context, decl, attr)) return decl_poison(decl); break; case ATTRIBUTE_ALIGN: had = decl->alignment != 0; @@ -1228,7 +1264,7 @@ static inline bool sema_analyse_global(Context *context, Decl *decl) break; case ATTRIBUTE_SECTION: had = decl->section != NULL; - decl->section = attr->expr->const_expr.string.chars; + if (!sema_check_section(context, decl, attr)) return decl_poison(decl); break; case ATTRIBUTE_ALIGN: had = decl->alignment != 0; diff --git a/src/utils/lib.h b/src/utils/lib.h index 1dcb290ca..2e0f73495 100644 --- a/src/utils/lib.h +++ b/src/utils/lib.h @@ -430,6 +430,7 @@ static inline StringSlice strtoslice(const char *data) { return (StringSlice) { data, strlen(data) }; } +void slicetrim(StringSlice *slice); #define MAX(_a, _b) ({ \ typeof(_a) __a__ = (_a); \ diff --git a/src/utils/stringutils.c b/src/utils/stringutils.c index 19d7bf099..e888e74b9 100644 --- a/src/utils/stringutils.c +++ b/src/utils/stringutils.c @@ -42,6 +42,23 @@ StringSlice strnexttok(StringSlice *slice, char separator) return result; } +void slicetrim(StringSlice *slice) +{ + size_t i; + for (i = 0; i < slice->len; i++) + { + if (slice->ptr[i] != ' ') break; + } + slice->ptr += i; + slice->len -= i; + for (i = slice->len; i > 0; i--) + { + if (slice->ptr[i - 1] != ' ') break; + } + slice->len = i; +} + + char *strcopy(const char *start, size_t len) { char *buffer = malloc_arena(len + 1); diff --git a/test/src/tester.py b/test/src/tester.py index 1485579ea..ec8e3b330 100644 --- a/test/src/tester.py +++ b/test/src/tester.py @@ -158,6 +158,8 @@ class Issues: if (line.startswith("warning:")): print("TODO" + line) exit(-1) + elif (line.startswith("target:")): + self.arch = line[7:].strip() elif (line.startswith("error:")): line = line[6:].strip() self.errors[self.current_file.filename + ":%d" % (self.line + self.current_file.line_offset)] = line diff --git a/test/test_suite/abi/macho_section_attributes.c3 b/test/test_suite/abi/macho_section_attributes.c3 new file mode 100644 index 000000000..ee72e6b92 --- /dev/null +++ b/test/test_suite/abi/macho_section_attributes.c3 @@ -0,0 +1,8 @@ +// #target: x64-darwin + +int foo @section("foo, 12345678901234567 "); // #error: Mach-o requires the section to be at the most 16 characters +int bar @section("foo, "); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly? +int baz @section("foo"); // #error: Mach-o requires 'segment,section' as the format, did you type it correctly? +int abc @section("foo,b,c,d,e,f"); // #error: Too many parts to the Mach-o section description. +int def @section("foo,b,c,d"); +