mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add --list-asm to view all supported asm instructions.
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
- Add `--echo-prefix` to edit the prefix with `$echo` statements. Supports {FILE} and {LINE}
|
||||
- Catch accidental `foo == BAR;` where `foo = BAR;` was most likely intended. #2274
|
||||
- Improve error message when doing a rethrow in a function that doesn't return an optional.
|
||||
- Add `--list-asm` to view all supported `asm` instructions.
|
||||
|
||||
### Fixes
|
||||
- mkdir/rmdir would not work properly with substring paths on non-windows platforms.
|
||||
|
||||
@@ -594,6 +594,7 @@ typedef struct BuildOptions_
|
||||
bool print_precedence;
|
||||
bool print_linking;
|
||||
bool print_env;
|
||||
bool print_asm;
|
||||
bool benchmarking;
|
||||
bool testing;
|
||||
} BuildOptions;
|
||||
|
||||
@@ -191,6 +191,7 @@ static void usage(bool full)
|
||||
print_opt("--list-manifest-properties", "List all available keys used in manifest.json files.");
|
||||
print_opt("--list-targets", "List all architectures the compiler supports.");
|
||||
print_opt("--list-type-properties", "List all type properties.");
|
||||
print_opt("--list-asm", "List all asm instructions for the current target.");
|
||||
PRINTF("");
|
||||
print_opt("--print-output", "Print the object files created to stdout.");
|
||||
print_opt("--print-input", "Print inputted C3 files to stdout.");
|
||||
@@ -1007,6 +1008,11 @@ static void parse_option(BuildOptions *options)
|
||||
options->command = COMMAND_PRINT_SYNTAX;
|
||||
return;
|
||||
}
|
||||
if (match_longopt("list-asm"))
|
||||
{
|
||||
options->print_asm = true;
|
||||
return;
|
||||
}
|
||||
if (match_longopt("list-project-properties"))
|
||||
{
|
||||
options->print_project_properties = true;
|
||||
|
||||
@@ -747,6 +747,172 @@ bool asm_is_supported(ArchType arch)
|
||||
}
|
||||
}
|
||||
|
||||
static void scratch_append_bit(const char *name, const char *string, bool *has_print_reg)
|
||||
{
|
||||
if (*has_print_reg)
|
||||
{
|
||||
scratch_buffer_append("/");
|
||||
}
|
||||
else
|
||||
{
|
||||
*has_print_reg = true;
|
||||
}
|
||||
scratch_buffer_append(name);
|
||||
scratch_buffer_append(string);
|
||||
}
|
||||
|
||||
static void scratch_append_bits(const char *name, AsmArgBits bits)
|
||||
{
|
||||
bool has_print = false;
|
||||
if (bits & ARG_BITS_512) scratch_append_bit(name, "512", &has_print);
|
||||
if (bits & ARG_BITS_256) scratch_append_bit(name, "256", &has_print);
|
||||
if (bits & ARG_BITS_128) scratch_append_bit(name, "128", &has_print);
|
||||
if (bits & ARG_BITS_80) scratch_append_bit(name, "80", &has_print);
|
||||
if (bits & ARG_BITS_64) scratch_append_bit(name, "64", &has_print);
|
||||
if (bits & ARG_BITS_32) scratch_append_bit(name, "32", &has_print);
|
||||
if (bits & ARG_BITS_20) scratch_append_bit(name, "20", &has_print);
|
||||
if (bits & ARG_BITS_16) scratch_append_bit(name, "16", &has_print);
|
||||
if (bits & ARG_BITS_12) scratch_append_bit(name, "12", &has_print);
|
||||
if (bits & ARG_BITS_8) scratch_append_bit(name, "8", &has_print);
|
||||
if (bits & ARG_BITS_5) scratch_append_bit(name, "5", &has_print);
|
||||
}
|
||||
|
||||
static void arm_arg_to_scratch(AsmArgType type)
|
||||
{
|
||||
scratch_buffer_clear();
|
||||
if (type.is_write && !type.is_readwrite) scratch_buffer_append("w");
|
||||
if (type.is_readwrite) scratch_buffer_append("rw");
|
||||
if (scratch_buffer.len) scratch_buffer_append(":");
|
||||
bool has_print = false;
|
||||
if (type.imm_arg_ubits)
|
||||
{
|
||||
scratch_append_bits("immu", type.imm_arg_ubits);
|
||||
has_print = true;
|
||||
}
|
||||
if (type.imm_arg_ibits)
|
||||
{
|
||||
if (has_print) scratch_buffer_append("/");
|
||||
scratch_append_bits("imm", type.imm_arg_ibits);
|
||||
has_print = true;
|
||||
}
|
||||
if (type.ireg_bits)
|
||||
{
|
||||
if (has_print) scratch_buffer_append("/");
|
||||
scratch_append_bits("r", type.ireg_bits);
|
||||
has_print = true;
|
||||
}
|
||||
if (type.float_bits)
|
||||
{
|
||||
if (has_print) scratch_buffer_append("/");
|
||||
scratch_append_bits("f", type.float_bits);
|
||||
has_print = true;
|
||||
}
|
||||
if (type.vec_bits)
|
||||
{
|
||||
if (has_print) scratch_buffer_append("/");
|
||||
scratch_append_bits("v", type.vec_bits);
|
||||
has_print = true;
|
||||
}
|
||||
if (type.is_address)
|
||||
{
|
||||
if (has_print) scratch_buffer_append("/");
|
||||
scratch_buffer_append("mem");
|
||||
}
|
||||
}
|
||||
|
||||
static int comp(const void *a_ptr, const void *b_ptr)
|
||||
{
|
||||
const AsmInstruction *a = a_ptr;
|
||||
const AsmInstruction *b = b_ptr;
|
||||
if (a->name == b->name) return 0;
|
||||
if (!a->name) return -1;
|
||||
if (!b->name) return 1;
|
||||
return strcmp(a->name, b->name);
|
||||
}
|
||||
|
||||
static void print_arch_asm(PlatformTarget *target)
|
||||
{
|
||||
AsmInstruction instructions[ASM_INSTRUCTION_MAX];
|
||||
memcpy(instructions, target->instructions, sizeof(target->instructions));
|
||||
qsort(instructions, ASM_INSTRUCTION_MAX, sizeof(instructions[0]), comp);
|
||||
printf("+------------+--------------------------------+-----------------------------------------------------------------------+\n");
|
||||
printf("| instr | clobbers | args |\n");
|
||||
printf("+------------+--------------------------------+-----------------------------------------------------------------------+\n");
|
||||
for (int i = 0; i < ASM_INSTRUCTION_MAX; i++)
|
||||
{
|
||||
AsmInstruction *instruction = &instructions[i];
|
||||
if (!instruction->name) continue;
|
||||
printf("| %-10s | ", instruction->name);
|
||||
scratch_buffer_clear();
|
||||
Clobbers clobbers = instruction->mask;
|
||||
switch (target->arch)
|
||||
{
|
||||
case ARCH_TYPE_X86_64:
|
||||
case ARCH_TYPE_X86:
|
||||
{
|
||||
for (X86Clobbers cl = 0; cl <= X86_TMM7; cl++)
|
||||
{
|
||||
if (clobbers.mask[cl / 64] & (1ULL << (cl % 64)))
|
||||
{
|
||||
scratch_buffer_append(X86ClobberNames[cl]);
|
||||
scratch_buffer_append(", ");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ARCH_TYPE_AARCH64:
|
||||
case ARCH_TYPE_AARCH64_32:
|
||||
case ARCH_TYPE_AARCH64_BE:
|
||||
{
|
||||
for (Aarch64Clobbers cl = 0; cl <= AARCH64_V31; cl++)
|
||||
{
|
||||
if (clobbers.mask[cl / 64] & (1ULL << (cl % 64)))
|
||||
{
|
||||
scratch_buffer_append(Aarch64ClobberNames[cl]);
|
||||
scratch_buffer_append(", ");
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE
|
||||
}
|
||||
if (scratch_buffer.len) scratch_buffer.len -= 2;
|
||||
printf("%-30s | ", scratch_buffer_to_string());
|
||||
int len = 0;
|
||||
for (unsigned j = 0; j < instruction->param_count; j++)
|
||||
{
|
||||
if (j != 0)
|
||||
{
|
||||
len += 2;
|
||||
printf(", ");
|
||||
}
|
||||
arm_arg_to_scratch(instruction->param[j]);
|
||||
printf("%s", scratch_buffer_to_string());
|
||||
len += scratch_buffer.len;
|
||||
}
|
||||
for (int j = 0; j < 70 - len; j++) printf(" ");
|
||||
printf("|\n");
|
||||
}
|
||||
printf("+------------+--------------------------------+-----------------------------------------------------------------------+\n");
|
||||
}
|
||||
void print_asm(PlatformTarget *target)
|
||||
{
|
||||
init_asm(target);
|
||||
switch (target->arch)
|
||||
{
|
||||
case ARCH_TYPE_X86_64:
|
||||
case ARCH_TYPE_X86:
|
||||
case ARCH_TYPE_AARCH64:
|
||||
case ARCH_TYPE_AARCH64_32:
|
||||
case ARCH_TYPE_AARCH64_BE:
|
||||
print_arch_asm(target);
|
||||
return;
|
||||
default:
|
||||
printf("Printing ASM for target is not yet supported.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
void init_asm(PlatformTarget *target)
|
||||
{
|
||||
if (target->asm_initialized) return;
|
||||
|
||||
@@ -99,6 +99,10 @@ void compiler_init(BuildOptions *build_options)
|
||||
{
|
||||
compiler.context.should_print_environment = true;
|
||||
}
|
||||
if (build_options->print_asm)
|
||||
{
|
||||
compiler.context.should_print_asm = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void compiler_lex(void)
|
||||
@@ -1431,6 +1435,11 @@ void compile()
|
||||
print_build_env();
|
||||
exit_compiler(COMPILER_SUCCESS_EXIT);
|
||||
}
|
||||
if (compiler.context.should_print_asm)
|
||||
{
|
||||
print_asm(&compiler.platform);
|
||||
exit_compiler(COMPILER_SUCCESS_EXIT);
|
||||
}
|
||||
check_sanitizer_options(&compiler.build);
|
||||
resolve_libraries(&compiler.build);
|
||||
compiler.context.sources = compiler.build.sources;
|
||||
|
||||
@@ -1877,6 +1877,7 @@ typedef struct
|
||||
typedef struct
|
||||
{
|
||||
bool should_print_environment;
|
||||
bool should_print_asm;
|
||||
Ansi ansi;
|
||||
HTable modules;
|
||||
Module *core_module;
|
||||
@@ -2169,6 +2170,7 @@ Ast *copy_ast_defer(Ast *source_ast);
|
||||
TypeInfo *copy_type_info_single(TypeInfo *type_info);
|
||||
|
||||
void init_asm(PlatformTarget *target);
|
||||
void print_asm_list(PlatformTarget *target);
|
||||
AsmRegister *asm_reg_by_name(PlatformTarget *target, const char *name);
|
||||
AsmInstruction *asm_instr_by_name(const char *name);
|
||||
INLINE const char *asm_clobber_by_index(unsigned index);
|
||||
@@ -4322,4 +4324,5 @@ INLINE bool expr_is_valid_index(Expr *expr)
|
||||
const char *default_c_compiler(void);
|
||||
|
||||
void print_build_env(void);
|
||||
void print_asm(PlatformTarget *target);
|
||||
const char *os_type_to_string(OsType os);
|
||||
|
||||
Reference in New Issue
Block a user