mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 03:51:18 +00:00
187 lines
6.7 KiB
C
187 lines
6.7 KiB
C
#pragma once
|
|
|
|
#include "codegen_internal.h"
|
|
|
|
// 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.
|
|
|
|
#undef TB_Reg
|
|
#include <tb.h>
|
|
|
|
|
|
typedef enum
|
|
{
|
|
TBE_VALUE,
|
|
TBE_ADDRESS,
|
|
TBE_ADDRESS_OPTIONAL,
|
|
} TBBackendValueKind;
|
|
|
|
typedef struct
|
|
{
|
|
TBBackendValueKind kind: 5;
|
|
AlignSize alignment;
|
|
|
|
Type *type; // Should never be a distinct or canonical type.
|
|
|
|
TB_Reg reg;
|
|
TB_Reg failable;
|
|
} TBEValue;
|
|
|
|
typedef struct
|
|
{
|
|
Module *code_module;
|
|
const char *object_filename;
|
|
const char *ir_filename;
|
|
const char *asm_filename;
|
|
|
|
TB_Function **functions;
|
|
TB_Module *module;
|
|
TB_FeatureSet features;
|
|
|
|
struct
|
|
{
|
|
const char *name;
|
|
FunctionPrototype *prototype;
|
|
Type *rtype;
|
|
} cur_func;
|
|
Decl *curr_func;
|
|
TB_Function *f;
|
|
TB_Reg opt_var;
|
|
TB_Label catch_block;
|
|
TBEValue retval;
|
|
TB_Reg return_out;
|
|
TB_Reg optional_out;
|
|
struct
|
|
{
|
|
TB_Reg last_ptr;
|
|
TB_Reg stack_slot;
|
|
} debug;
|
|
} TildeContext;
|
|
|
|
|
|
TB_DataType tildetype(Type *type);
|
|
|
|
#define PUSH_OPT() TB_Label _old_catch = c->catch_block; TB_Reg _old_opt_var = c->opt_var
|
|
#define POP_OPT() c->catch_block = _old_catch; c->opt_var = _old_opt_var
|
|
|
|
|
|
// -- store ---
|
|
static inline void tilde_store_internal(TildeContext *c, TB_DataType type, TB_Reg addr, TB_Reg value, AlignSize alignment);
|
|
void tilde_store_to_ptr_raw_aligned(TildeContext *c, Type *type, TB_Reg addr, TB_Reg value, AlignSize alignment);
|
|
void tilde_store_to_ptr_raw(TildeContext *c, TB_Reg addr, TB_Reg value, Type *type);
|
|
void tilde_store_value_raw(TildeContext *c, TBEValue *destination, TB_Reg value);
|
|
void tilde_store_to_ptr_aligned(TildeContext *c, TB_Reg destination, TBEValue *value, AlignSize alignment);
|
|
void tilde_store_value_aligned(TildeContext *c, TB_Reg destination, TBEValue *value, AlignSize alignment);
|
|
void tilde_store(TildeContext *c, TBEValue *dst, TBEValue *value);
|
|
void tilde_store_decl_raw(TildeContext *c, Decl *decl, TB_Reg value);
|
|
TB_Reg tilde_load_natural_alignment(TildeContext *c, Type *type, TB_Reg pointer);
|
|
TB_Reg tilde_load_value_store(TildeContext *c, TBEValue *value);
|
|
void tilde_store_zero(TildeContext *c, Type *type, TB_Reg addr, AlignSize alignment);
|
|
void tilde_store_value_zero(TildeContext *c, TBEValue *to);
|
|
INLINE void tilde_store_to_ptr(TildeContext *c, TB_Reg destination, TBEValue *value);
|
|
|
|
// -- load ---
|
|
static inline TB_Reg tilde_load(TildeContext *c, TB_DataType type, TB_Reg addr, AlignSize alignment);
|
|
TB_Reg tilde_load_abi_alignment(TildeContext *c, Type *type, TB_Reg pointer);
|
|
TB_Reg tilde_load_value(TildeContext *c, TBEValue *value);
|
|
|
|
// -- value --
|
|
void value_set(TBEValue *value, TB_Reg val, Type *type);
|
|
void value_set_address(TBEValue *value, TB_Reg addr, Type *type, AlignSize alignment);
|
|
void value_set_address_abi_aligned(TBEValue *value, TB_Reg val, Type *type);
|
|
void value_set_decl_address(TildeContext *c, TBEValue *value, Decl *decl);
|
|
void value_set_decl(TildeContext *c, TBEValue *value, Decl *decl);
|
|
void value_addr(TildeContext *c, TBEValue *value);
|
|
|
|
static inline bool value_is_addr(TBEValue *value) { return value->kind == TBE_ADDRESS || value->kind == TBE_ADDRESS_OPTIONAL; }
|
|
void value_fold_optional(TildeContext *c, TBEValue *value);
|
|
void value_rvalue(TildeContext *c, TBEValue *value);
|
|
|
|
TB_Reg tilde_get_ref(TildeContext *c, Decl *decl);
|
|
TB_Reg tilde_get_opt_ref(TildeContext *c, Decl *decl);
|
|
TB_Reg tilde_get_const_int(TildeContext *c, Type *type, uint64_t i);
|
|
TB_Reg tilde_get_const_float(TildeContext *c, Type *type, double d);
|
|
TB_Register tilde_get_zero(TildeContext *c, Type *type);
|
|
|
|
// -- type ---
|
|
|
|
// -- instructions --
|
|
void tilde_emit_cond_br(TildeContext *c, TBEValue *value, TB_Label then_block, TB_Label else_block);
|
|
TB_Reg tilde_emit_lshr_fixed(TildeContext *c, Type *type, TB_Reg reg, int shift);
|
|
|
|
// -- stmt ---
|
|
void tilde_emit_stmt(TildeContext *c, Ast *ast);
|
|
|
|
// -- general ---
|
|
TB_Register tilde_emit_is_no_error(TildeContext *c, TB_Reg reg);
|
|
void tilde_emit_global_initializer(TildeContext *c, Decl *decl);
|
|
TB_Reg tilde_emit_alloca(TildeContext *c, Type *type, AlignSize alignment);
|
|
void tilde_emit_local_var_alloca(TildeContext *c, Decl *decl);
|
|
void tilde_emit_and_set_decl_alloca(TildeContext *c, Decl *decl);
|
|
INLINE TB_Linkage tilde_linkage_for_decl(Decl *decl);
|
|
void tilde_emit_parameter(TildeContext *c, TB_Reg *args, unsigned *arg_count_ref, ABIArgInfo *info, TBEValue *be_value, Type *type);
|
|
|
|
|
|
// -- expr --
|
|
void tilde_emit_expr(TildeContext *c, TBEValue *result, Expr *expr);
|
|
TBEValue tilde_emit_assign_expr(TildeContext *c, TBEValue *ref, Expr *expr, TB_Reg optional);
|
|
void tilde_emit_cast(TildeContext *c, CastKind cast_kind, Expr *expr, TBEValue *value, Type *to_type, Type *from_type);
|
|
|
|
// -- comparisons --
|
|
void tilde_emit_comp(TildeContext *c, TBEValue *result, TBEValue *lhs, TBEValue *rhs, BinaryOp binary_op);
|
|
void tilde_emit_int_comp(TildeContext *c, TBEValue *result, TBEValue *lhs, TBEValue *rhs, BinaryOp binary_op);
|
|
void tilde_emit_int_comp_zero(TildeContext *c, TBEValue *result, TBEValue *lhs, BinaryOp binary_op);
|
|
void tilde_emit_int_comp_raw(TildeContext *c, TBEValue *result, Type *lhs_type, Type *rhs_type, TB_Reg lhs_value, TB_Reg rhs_value, BinaryOp binary_op);
|
|
|
|
// -- optional --
|
|
void tilde_emit_jump_to_optional_exit(TildeContext *c, TB_Reg opt_value);
|
|
TB_Reg tilde_emit_is_no_opt(TildeContext *c, TB_Reg error_value);
|
|
|
|
|
|
// -- jumps ---
|
|
bool tilde_emit_goto_if_needed(TildeContext *c, TB_Label jump);
|
|
INLINE void tilde_emit_block(TildeContext *c, TB_Label block);
|
|
|
|
void tilde_emit_memclear_size_align(TildeContext *c, TB_Register ref, uint64_t size, AlignSize align);
|
|
|
|
#define EMIT_LOC(x, y) do { } while(0)
|
|
|
|
|
|
static inline void tilde_store_internal(TildeContext *c, TB_DataType type, TB_Reg addr, TB_Reg value, AlignSize alignment)
|
|
{
|
|
assert(alignment > 0);
|
|
tb_inst_store(c->f, type, addr, value, alignment);
|
|
}
|
|
|
|
static inline TB_Reg tilde_load(TildeContext *c, TB_DataType type, TB_Reg addr, AlignSize alignment)
|
|
{
|
|
assert(alignment > 0);
|
|
return tb_inst_load(c->f, type, addr, alignment);
|
|
}
|
|
|
|
static inline TB_Reg decl_reg(Decl *decl)
|
|
{
|
|
if (decl->decl_kind == DECL_VAR && decl->var.kind == VARDECL_UNWRAPPED) return decl_reg(decl->var.alias);
|
|
assert(!decl->is_value);
|
|
return decl->tb_register;
|
|
}
|
|
|
|
TB_DataType tilde_get_int_type_of_bytesize(int byte_size);
|
|
TB_FunctionPrototype *tilde_get_func_prototype(TildeContext *c, FunctionPrototype *prototype);
|
|
INLINE TB_Linkage tilde_linkage_for_decl(Decl *decl)
|
|
{
|
|
if (!decl->is_external_visible && decl->visibility == VISIBLE_LOCAL) return TB_LINKAGE_PRIVATE;
|
|
return TB_LINKAGE_PUBLIC;
|
|
}
|
|
|
|
INLINE void tilde_store_to_ptr(TildeContext *c, TB_Reg destination, TBEValue *value)
|
|
{
|
|
return tilde_store_to_ptr_aligned(c, destination, value, type_alloca_alignment(value->type));
|
|
}
|
|
|
|
INLINE void tilde_emit_block(TildeContext *c, TB_Label block)
|
|
{
|
|
tb_inst_set_label(c->f, block);
|
|
}
|