Files
c3c/src/compiler/codegen_asm.c
2022-09-05 13:29:03 +02:00

119 lines
3.0 KiB
C

// Copyright (c) 2022 Christoffer Lerno. All rights reserved.
// Use of this source code is governed by a LGPLv3.0
// a copy of which can be found in the LICENSE file.
#include "codegen_internal.h"
static inline void codegen_create_x86att_arg(AsmInlineBlock *block, unsigned input_offset, Expr *expr)
{
ExprAsmArg *arg = &expr->expr_asm_arg;
switch (arg->kind)
{
case ASM_ARG_INT:
scratch_buffer_append("$$");
scratch_buffer_append_unsigned_int(arg->value);
return;
case ASM_ARG_REG:
{
AsmRegister *reg = arg->reg.ref;
scratch_buffer_append_char('%');
scratch_buffer_append(&reg->name[1]);
return;
}
case ASM_ARG_VALUE:
scratch_buffer_append_char('$');
scratch_buffer_append_unsigned_int(arg->index + input_offset);
return;
case ASM_ARG_MEMVAR:
case ASM_ARG_REGVAR:
scratch_buffer_append_char('$');
if (arg->ident.is_input && !arg->ident.copy_output)
{
scratch_buffer_append_unsigned_int(arg->index + input_offset);
}
else
{
scratch_buffer_append_unsigned_int(arg->index);
}
return;
case ASM_ARG_ADDR:
if (arg->offset)
{
if (arg->neg_offset) scratch_buffer_append_char('-');
scratch_buffer_append_unsigned_int(arg->offset);
}
scratch_buffer_append_char('(');
if (arg->base)
{
codegen_create_x86att_arg(block, input_offset, exprptr(arg->base));
}
if (arg->idx)
{
scratch_buffer_append_char(',');
codegen_create_x86att_arg(block, input_offset, exprptr(arg->idx));
scratch_buffer_append_char(',');
switch (arg->offset_type)
{
case ASM_SCALE_1:
scratch_buffer_append_char('1');
break;
case ASM_SCALE_2:
scratch_buffer_append_char('2');
break;
case ASM_SCALE_4:
scratch_buffer_append_char('4');
break;
case ASM_SCALE_8:
scratch_buffer_append_char('8');
break;
default:
UNREACHABLE
}
}
scratch_buffer_append_char(')');
return;
case ASM_ARG_ADDROF:
TODO
}
UNREACHABLE
}
static inline char *codegen_create_x86_att_asm(AsmInlineBlock *block)
{
AstId next = block->asm_stmt;
scratch_buffer_clear();
unsigned input_arg_offset = vec_size(block->output_vars);
while (next)
{
Ast *ast = astptr(next);
next = ast->next;
scratch_buffer_append(ast->asm_stmt.instruction);
Expr** args = ast->asm_stmt.args;
unsigned arg_count = vec_size(args);
scratch_buffer_append_char(' ');
if (arg_count > 1)
{
codegen_create_x86att_arg(block, input_arg_offset, args[1]);
scratch_buffer_append(", ");
}
if (arg_count)
{
codegen_create_x86att_arg(block, input_arg_offset, args[0]);
}
scratch_buffer_append_char('\n');
}
return scratch_buffer_to_string();
}
const char *codegen_create_asm(Ast *ast, ClobberList *clobber_list)
{
assert(ast->ast_kind == AST_ASM_BLOCK_STMT);
scratch_buffer_clear();
AsmInlineBlock *block = ast->asm_block_stmt.block;
if (platform_target.arch == ARCH_TYPE_X86_64 || platform_target.arch == ARCH_TYPE_X86)
{
return codegen_create_x86_att_asm(block);
}
UNREACHABLE
}