mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 20:11:17 +00:00
119 lines
3.0 KiB
C
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(®->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
|
|
} |