Do the parsing of all models used in the kernel and output the predefines for arm64 & riscv. Reported-by: Paul Walmsley <paul.walmsley@xxxxxxxxxx> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@xxxxxxxxx> --- lib.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib.h | 13 +++++++++ 2 files changed, 99 insertions(+) diff --git a/lib.c b/lib.c index e9e637d29..84b5be6a8 100644 --- a/lib.c +++ b/lib.c @@ -328,6 +328,7 @@ static int arch_msize_long = 0; int arch_m64 = ARCH_M64_DEFAULT; int arch_big_endian = ARCH_BIG_ENDIAN; int arch_mach = MACH_NATIVE; +int arch_cmodel = CMODEL_UNKNOWN; #define CMDLINE_INCLUDE 20 @@ -470,6 +471,26 @@ static char **handle_switch_m(char *arg, char **next) arch_big_endian = 1; } else if (!strcmp(arg, "mlittle-endian")) { arch_big_endian = 0; + } else if (!strncmp(arg, "mcmodel", 7)) { + arg += 7; + if (*arg++ != '=') + die("missing argument for -mcmodel"); + else if (!strcmp(arg, "kernel")) + arch_cmodel = CMODEL_KERNEL; + else if (!strcmp(arg, "large")) + arch_cmodel = CMODEL_LARGE; + else if (!strcmp(arg, "medany")) + arch_cmodel = CMODEL_MEDANY; + else if (!strcmp(arg, "medium")) + arch_cmodel = CMODEL_MEDIUM; + else if (!strcmp(arg, "medlow")) + arch_cmodel = CMODEL_MEDLOW; + else if (!strcmp(arg, "small")) + arch_cmodel = CMODEL_SMALL; + else if (!strcmp(arg, "tiny")) + arch_cmodel = CMODEL_TINY; + else + die("invalid argument for -mcmodel=%s", arg); } return next; } @@ -488,6 +509,20 @@ static void handle_arch_finalize(void) if (fpie > fpic) fpic = fpie; + + switch (arch_mach) { + case MACH_ARM64: + if (arch_cmodel == CMODEL_UNKNOWN) + arch_cmodel = CMODEL_SMALL; + break; + case MACH_RISCV32: + case MACH_RISCV64: + if (arch_cmodel == CMODEL_UNKNOWN) + arch_cmodel = CMODEL_MEDLOW; + if (fpic) + arch_cmodel = CMODEL_PIC; + break; + } } static const char *match_option(const char *arg, const char *prefix) @@ -1213,6 +1248,55 @@ static void predefined_ctype(const char *name, struct symbol *type, int flags) predefined_width(name, bits); } +static void predefined_cmodel(void) +{ + const char *pre, *suf; + const char *def = NULL; + switch (arch_mach) { + case MACH_ARM64: + pre = "__AARCH64_CMODEL_"; + suf = "__"; + switch (arch_cmodel) { + case CMODEL_LARGE: + def = "LARGE"; + break; + case CMODEL_SMALL: + def = "SMALL"; + break; + case CMODEL_TINY: + def = "TINY"; + break; + default: + break; + } + break; + case MACH_RISCV32: + case MACH_RISCV64: + pre = "__riscv_cmodel_"; + suf = ""; + switch (arch_cmodel) { + case CMODEL_MEDLOW: + def = "medlow"; + break; + case CMODEL_MEDANY: + def = "medany"; + break; + case CMODEL_PIC: + def = "pic"; + break; + default: + break; + } + break; + default: + break; + } + + if (!def) + return; + add_pre_buffer("#weak_define %s%s%s 1\n", pre, def, suf); +} + static void predefined_macros(void) { predefine("__CHECKER__", 0, "1"); @@ -1406,6 +1490,8 @@ static void predefined_macros(void) predefine("__pie__", 0, "%d", fpie); predefine("__PIE__", 0, "%d", fpie); } + + predefined_cmodel(); } static void create_builtin_stream(void) diff --git a/lib.h b/lib.h index b3616fd45..f6dea8ca2 100644 --- a/lib.h +++ b/lib.h @@ -207,6 +207,19 @@ extern int arch_m64; extern int arch_big_endian; extern int arch_mach; +enum { + CMODEL_UNKNOWN, + CMODEL_KERNEL, + CMODEL_LARGE, + CMODEL_MEDANY, + CMODEL_MEDIUM, + CMODEL_MEDLOW, + CMODEL_PIC, + CMODEL_SMALL, + CMODEL_TINY, +}; +extern int arch_cmodel; + extern void dump_macro_definitions(void); extern struct symbol_list *sparse_initialize(int argc, char **argv, struct string_list **files); extern struct symbol_list *__sparse(char *filename); -- 2.23.0