Skip to content

Commit

Permalink
Begin work on asm label support.
Browse files Browse the repository at this point in the history
  • Loading branch information
lerno committed Nov 23, 2024
1 parent 9d99d55 commit b2724ca
Show file tree
Hide file tree
Showing 10 changed files with 54 additions and 16 deletions.
10 changes: 10 additions & 0 deletions src/compiler/codegen_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
#define CAST_AND_EXTEND(x, n) \
(((int64_t)((x) << (64 - (n)))) >> (64 - (n)))

INLINE bool codegen_asm_label(Ast *ast)
{
if (ast->ast_kind != AST_ASM_LABEL) return false;
scratch_buffer_printf("${:private}%s.${:uid}:\n", ast->asm_label);
return true;
}

static inline void codegen_create_x86att_arg(AsmInlineBlock *block, unsigned input_offset, Expr *expr)
{
ExprAsmArg *arg = &expr->expr_asm_arg;
Expand Down Expand Up @@ -177,6 +184,7 @@ static inline char *codegen_create_x86_att_asm(AsmInlineBlock *block)
{
Ast *ast = astptr(next);
next = ast->next;
if (codegen_asm_label(ast)) continue;
scratch_buffer_append(ast->asm_stmt.instruction);
Expr** args = ast->asm_stmt.args;
unsigned arg_count = vec_size(args);
Expand All @@ -201,6 +209,7 @@ static inline char *codegen_create_aarch64_asm(AsmInlineBlock *block)
{
Ast *ast = astptr(next);
next = ast->next;
if (codegen_asm_label(ast)) continue;
scratch_buffer_append(ast->asm_stmt.instruction);
Expr** args = ast->asm_stmt.args;
unsigned arg_count = vec_size(args);
Expand All @@ -225,6 +234,7 @@ static inline char *codegen_create_riscv_asm(AsmInlineBlock *block)
{
Ast *ast = astptr(next);
next = ast->next;
if (codegen_asm_label(ast)) continue;
scratch_buffer_append(ast->asm_stmt.instruction);
Expr** args = ast->asm_stmt.args;
unsigned arg_count = vec_size(args);
Expand Down
4 changes: 3 additions & 1 deletion src/compiler/compiler_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -1376,8 +1376,8 @@ typedef struct
typedef struct
{
Clobbers clobbers;
const char *asm_block;
AstId asm_stmt;
Ast **labels;
ExprAsmArg **output_vars;
ExprAsmArg **input;
} AsmInlineBlock;
Expand Down Expand Up @@ -1454,8 +1454,10 @@ typedef struct Ast_
union
{
FlowCommon flow; // Shared struct

AstAsmBlock asm_block_stmt;
AstAsmStmt asm_stmt;
const char *asm_label;
AstAssertStmt assert_stmt; // 16
AstCaseStmt case_stmt; // 32
AstCompoundStmt compound_stmt; // 12
Expand Down
1 change: 1 addition & 0 deletions src/compiler/copying.c
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,7 @@ Ast *ast_copy_deep(CopyStruct *c, Ast *source)
MACRO_COPY_EXPRID(ast->nextcase_stmt.expr);
break;
case AST_NOP_STMT:
case AST_ASM_LABEL:
break;
case AST_BLOCK_EXIT_STMT:
case AST_RETURN_STMT:
Expand Down
1 change: 1 addition & 0 deletions src/compiler/enums.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ typedef enum
AST_POISONED,
AST_ASM_STMT,
AST_ASM_BLOCK_STMT,
AST_ASM_LABEL,
AST_ASSERT_STMT,
AST_BREAK_STMT,
AST_CASE_STMT,
Expand Down
1 change: 1 addition & 0 deletions src/compiler/llvm_codegen_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -1612,6 +1612,7 @@ void llvm_emit_stmt(GenContext *c, Ast *ast)
case AST_FOREACH_STMT:
case AST_CONTRACT:
case AST_ASM_STMT:
case AST_ASM_LABEL:
case AST_CONTRACT_FAULT:
case AST_CASE_STMT:
case AST_DEFAULT_STMT:
Expand Down
8 changes: 8 additions & 0 deletions src/compiler/parse_stmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,14 @@ static inline Expr *parse_asm_expr(ParseContext *c)
static inline Ast *parse_asm_stmt(ParseContext *c)
{
Ast *asm_stmt = ast_new_curr(c, AST_ASM_STMT);
if (tok_is(c, TOKEN_CONST_IDENT))
{
asm_stmt->asm_label = symstr(c);
advance_and_verify(c, TOKEN_CONST_IDENT);
asm_stmt->ast_kind = AST_ASM_LABEL;
TRY_CONSUME_OR_RET(TOKEN_COLON, "Expected a ':' to terminate the label.", poisoned_ast);
return asm_stmt;
}
if (!tok_is(c, TOKEN_IDENT) && !tok_is(c, TOKEN_INT))
{
PRINT_ERROR_HERE("Expected an asm instruction here.");
Expand Down
21 changes: 6 additions & 15 deletions src/compiler/sema_asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ static inline bool sema_check_asm_arg_addr(SemaContext *context, AsmInlineBlock
{
if (!arg_type.is_address)
{
SEMA_ERROR(expr, "An address cannot appear in this slot.");
return false;
RETURN_SEMA_ERROR(expr, "An address cannot appear in this slot.");
}
ExprAsmArg *asm_arg = &expr->expr_asm_arg;
Expr *base = exprptr(asm_arg->base);
Expand All @@ -207,8 +206,7 @@ static inline bool sema_check_asm_arg_addr(SemaContext *context, AsmInlineBlock
TODO
break;
default:
SEMA_ERROR(expr, "Expected a register here.");
return false;
RETURN_SEMA_ERROR(expr, "Expected a register here.");
}
Expr *index = exprptrzero(asm_arg->idx);

Expand All @@ -232,8 +230,7 @@ static inline bool sema_check_asm_arg_addr(SemaContext *context, AsmInlineBlock
}
if (bit_size != index_size)
{
SEMA_ERROR(index, "Expected the same register size as for the base value.");
return false;
RETURN_SEMA_ERROR(index, "Expected the same register size as for the base value.");
}
}
if ((compiler.platform.arch == ARCH_TYPE_RISCV32 ||
Expand All @@ -243,8 +240,7 @@ static inline bool sema_check_asm_arg_addr(SemaContext *context, AsmInlineBlock
if ((asm_arg->neg_offset && asm_arg->offset > abs(INT12_MIN)) ||
(!asm_arg->neg_offset && asm_arg->offset > INT12_MAX))
{
SEMA_ERROR(expr, "RISC-V offset limited to 12-bits signed.");
return false;
RETURN_SEMA_ERROR(expr, "RISC-V offset limited to 12-bits signed.");
}
}

Expand All @@ -256,15 +252,10 @@ static inline bool sema_check_asm_arg_reg(SemaContext *context, AsmInlineBlock *
{
const char *name = expr->expr_asm_arg.reg.name;
AsmRegister *reg = expr->expr_asm_arg.reg.ref = asm_reg_by_name(&compiler.platform, name);
if (!reg)
{
SEMA_ERROR(expr, "Expected a valid register name.");
return false;
}
if (!reg) RETURN_SEMA_ERROR(expr, "Expected a valid register name.");
if (!sema_reg_is_valid_in_slot(reg, arg_type))
{
SEMA_ERROR(expr, "'%s' is not valid in this slot.", reg->name);
return false;
RETURN_SEMA_ERROR(expr, "'%s' is not valid in this slot.", reg->name);
}
if (arg_type.is_write)
{
Expand Down
1 change: 1 addition & 0 deletions src/compiler/sema_decls.c
Original file line number Diff line number Diff line change
Expand Up @@ -3700,6 +3700,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er
continue;
case AST_POISONED:
case AST_ASM_STMT:
case AST_ASM_LABEL:
case AST_ASM_BLOCK_STMT:
case AST_ASSERT_STMT:
case AST_BREAK_STMT:
Expand Down
1 change: 1 addition & 0 deletions src/compiler/sema_liveness.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ static void sema_trace_stmt_liveness(Ast *ast)
sema_trace_stmt_liveness(astptr(ast->defer_stmt.body));
return;
case AST_NOP_STMT:
case AST_ASM_LABEL:
return;
case AST_COMPOUND_STMT:
sema_trace_stmt_chain_liveness(ast->compound_stmt.first_stmt);
Expand Down
22 changes: 22 additions & 0 deletions src/compiler/sema_stmts.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,22 @@ static bool sema_analyse_require(SemaContext *context, Ast *directive, AstId **a
static bool sema_analyse_ensure(SemaContext *context, Ast *directive);
static bool sema_analyse_optional_returns(SemaContext *context, Ast *directive);

static inline bool sema_analyse_asm_label(SemaContext *context, AsmInlineBlock *block, Ast *label)
{
const char *name = label->asm_label;
FOREACH(Ast *, other, block->labels)
{
if (name == other->asm_label)
{
SEMA_ERROR(label, "Duplicate ASM label '%s'.", name);
SEMA_NOTE(other, "The previous definition was here.");
return false;
}
}
vec_add(block->labels, label);
return true;
}

static inline bool sema_analyse_asm_stmt(SemaContext *context, Ast *stmt)
{
if (stmt->asm_block_stmt.is_string) return sema_analyse_asm_string_stmt(context, stmt);
Expand All @@ -68,6 +84,11 @@ static inline bool sema_analyse_asm_stmt(SemaContext *context, Ast *stmt)
{
Ast *ast = astptr(ast_id);
ast_id = ast->next;
if (ast->ast_kind == AST_ASM_LABEL)
{
sema_analyse_asm_label(context, block, ast);
continue;
}
if (!sema_analyse_asm(context, block, ast)) return false;
}
return true;
Expand Down Expand Up @@ -2910,6 +2931,7 @@ static inline bool sema_analyse_statement_inner(SemaContext *context, Ast *state
case AST_IF_CATCH_SWITCH_STMT:
case AST_CONTRACT:
case AST_ASM_STMT:
case AST_ASM_LABEL:
case AST_CONTRACT_FAULT:
UNREACHABLE
case AST_DECLS_STMT:
Expand Down

0 comments on commit b2724ca

Please sign in to comment.