From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp2.migadu.com ([2001:41d0:303:e16b::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id AMHiEIHfLGaeNQEAe85BDQ:P1 (envelope-from ) for ; Sat, 27 Apr 2024 13:20:33 +0200 Received: from aspmx1.migadu.com ([2001:41d0:303:e16b::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp2.migadu.com with LMTPS id AMHiEIHfLGaeNQEAe85BDQ (envelope-from ) for ; Sat, 27 Apr 2024 13:20:33 +0200 X-Envelope-To: patches@johnnyrichard.com Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=mnz737eG; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=jwONVnCB; spf=pass (aspmx1.migadu.com: domain of lists@sr.ht designates 46.23.81.152 as permitted sender) smtp.mailfrom=lists@sr.ht; dmarc=pass (policy=quarantine) header.from=johnnyrichard.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1714216833; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id: list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=wwbOA/vLO+SV8pVyLxuRNuL0j84hTZseAHH3SUJYb4Y=; b=HTrSKmL0DcCpiauAUfNjaNSzO0KjkzBSEYi8dahsGDudECmYR+jmq/VlINcNBIhuoCN1d8 FNo2PiDrRCZjeinnOWlVis2O/iUoLbNpLF4zlCQvhhr34FD83Y1NfCve3JuD1bx7eYlA4N fIHX33lyh2G+eGDvvFTGm5XZIFqV8FemMvbJ2GXoqKgsj5JuH0E/PYQln0G6bNHMFkTEbX 0/LhkO2GAiAE9m6IXPpZisle1BgpuKc8vz74oaHon2U/NIqPPAjGzDkOvvWH3wCtsLfK5L qlJ17b20oj4nHbIBak0W4OWtVSVoCV4FE+I8V6dVlHdNyUI+vxg1hVacP0hVOw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=lists.sr.ht header.s=20240113 header.b=mnz737eG; dkim=pass header.d=johnnyrichard.com header.s=key1 header.b=jwONVnCB; spf=pass (aspmx1.migadu.com: domain of lists@sr.ht designates 46.23.81.152 as permitted sender) smtp.mailfrom=lists@sr.ht; dmarc=pass (policy=quarantine) header.from=johnnyrichard.com ARC-Seal: i=1; s=key1; d=johnnyrichard.com; t=1714216833; a=rsa-sha256; cv=none; b=RP1qjkMQjrom0f7oORdwh8adtwbujwc7JzzvwesJ/brFv+9dk4HpfVfNhYGm66mHMfFqsu C40S6TBzupVJdJanQh51kcTuEi49seDhBG7OK3qqzPSRx5fQVNkCndl/DXOmJ4/sCiThqR gV5m2g1OgjAw/CECf8xPoqzdUHX4CurI1y07JEaU4+Zkz/L6laLVR5oJtakBNHyRHadpM0 Sg9Hy0s0C4WLoPNqqmO13WdalNYfa+M0U3NJffSA2ndsn3EgTFK5G61zOVzi50LVcCXuBn U2DJcGeyhBil0uu68oLhfzhSzPQLmPFMzXSpUahxHDHBkrefmpoTWdFU3wxA5A== Received: from mail-a.sr.ht (mail-a.sr.ht [46.23.81.152]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id 2A8D23913E for ; Sat, 27 Apr 2024 13:20:30 +0200 (CEST) DKIM-Signature: a=rsa-sha256; bh=KTvRdGeAyXr9zkhZfC1CMmphHPf9+xKMiCmcy1mHtDY=; c=simple/simple; d=lists.sr.ht; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-Unsubscribe:List-Subscribe:List-Archive:List-Post:List-ID; q=dns/txt; s=20240113; t=1714216829; v=1; b=mnz737eGQiJO7nlg2HnH5YJQc/b/cc2pCAeV5q32jSySF186+MluKHZHjkgUH8pcuNYKHJ1G TyjKZ5jWkCDzi6X71fi8U9UQyeyUw7CkLjpjX7LxjEizeNYCSKkG4Gi+zGOKN9X7wuEvAGa4Oi+ mr76x40N2NyU6AZ/HgVR2OQHZOqyeF8VZCriyGdGBEhAknWHWzBuXcxOomPT+ChD8jK3qkQ46hT CXqXTtPg4sCI13cYYCEE73e2MFMl5Svs/nyIcoXhDS4azpEWhY0eg35WmuYQTn2PNXlIBogfsvQ G63feJMPhtETyEaAs1L6Rq9m0WauTHrLAOQ4b2wmnOUxQ== Received: from lists.sr.ht (unknown [IPv6:2a03:6000:1813:1337::154]) by mail-a.sr.ht (Postfix) with ESMTPSA id 3716C203EB for ; Sat, 27 Apr 2024 11:20:29 +0000 (UTC) Received: from out-175.mta0.migadu.com (out-175.mta0.migadu.com [IPv6:2001:41d0:1004:224b::af]) by mail-a.sr.ht (Postfix) with ESMTPS id 8574A202E6 for <~johnnyrichard/olang-devel@lists.sr.ht>; Sat, 27 Apr 2024 11:20:28 +0000 (UTC) X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=johnnyrichard.com; s=key1; t=1714216828; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=wwbOA/vLO+SV8pVyLxuRNuL0j84hTZseAHH3SUJYb4Y=; b=jwONVnCBJI0vQwutBTzYaR/zODzvPB7oZzR9w6TZe1IY8GE3LAoEqjIH9zaxCS0ejtEdRn CqFkDATsMjkyUpvMtFPwlEQ13lOBRQIE6Euhq0mZ+UgY1VIxdmj6T+rm7O6xWjgR5BLKDD ZbghGXtIZZ0EY2JoXHU+dlCpH1wgVyBXzCLX9GwJXF5pr/u6Ip+5x27XBdhW7T7FaCPNh5 99uD/3u0Vh5XQ3lKUNl1XbWees08TGjOGQsuSl8R0PHoIW1ULBDmCZql3srZFzEAEjOGLb eAteVE0agZmQfsH/soEF3UX6mM4t2A9aqnQhEgOhHIdMB3c9vFArTR7YiE4q+A== From: Johnny Richard To: ~johnnyrichard/olang-devel@lists.sr.ht Cc: Johnny Richard Subject: [PATCH olang v1 2/2] codegen: x86_64: implement binary operations Date: Sat, 27 Apr 2024 14:14:12 +0200 Message-ID: <20240427121832.203068-3-johnny@johnnyrichard.com> In-Reply-To: <20240427121832.203068-1-johnny@johnnyrichard.com> References: <20240427121832.203068-1-johnny@johnnyrichard.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Sourcehut-Patchset-Status: PROPOSED List-Unsubscribe: List-Subscribe: List-Archive: Archived-At: List-Post: List-ID: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel.lists.sr.ht> Sender: ~johnnyrichard/olang-devel <~johnnyrichard/olang-devel@lists.sr.ht> X-Migadu-Flow: FLOW_IN X-Migadu-Country: NL X-Migadu-Spam-Score: -9.14 X-Spam-Score: -9.14 X-Migadu-Queue-Id: 2A8D23913E X-Migadu-Scanner: mx13.migadu.com X-TUID: 9r4ISKwhm8vF In order to simplify most of the binary operation expressions we are using stack to store previous execution. It makes the implementation easy but inefficient. We can optimize this codegen in a near future as soon as re get IR in place. This change also include a small fix on binary operation precedence for TOKEN_CMP_EQ. Signed-off-by: Johnny Richard --- examples/sum.ol | 3 + src/codegen_linux_x86_64.c | 232 ++++++++++++++++++++++++++++++++++++- src/parser.c | 2 +- 3 files changed, 232 insertions(+), 5 deletions(-) create mode 100644 examples/sum.ol diff --git a/examples/sum.ol b/examples/sum.ol new file mode 100644 index 0000000..b724088 --- /dev/null +++ b/examples/sum.ol @@ -0,0 +1,3 @@ +fn main(): u32 { + return 1 + 4 + 60 + 4 +} diff --git a/src/codegen_linux_x86_64.c b/src/codegen_linux_x86_64.c index 72db1c6..0accef4 100644 --- a/src/codegen_linux_x86_64.c +++ b/src/codegen_linux_x86_64.c @@ -23,6 +23,8 @@ #define SYS_exit (60) +size_t label_index; + static void codegen_linux_x86_64_emit_start_entrypoint(FILE *out); @@ -32,6 +34,7 @@ codegen_linux_x86_64_emit_function(FILE *out, ast_fn_definition_t *fn); void codegen_linux_x86_64_emit_program(FILE *out, ast_node_t *node) { + label_index = 0; codegen_linux_x86_64_emit_start_entrypoint(out); assert(node->kind == AST_NODE_PROGRAM); @@ -56,6 +59,12 @@ codegen_linux_x86_64_emit_start_entrypoint(FILE *out) fprintf(out, " syscall\n"); } +static size_t +codegen_linux_x86_64_get_next_label(void) +{ + return ++label_index; +} + static void codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node) { @@ -63,14 +72,229 @@ codegen_linux_x86_64_emit_expression(FILE *out, ast_node_t *expr_node) case AST_NODE_LITERAL: { ast_literal_t literal_u32 = expr_node->data.as_literal; assert(literal_u32.kind == AST_LITERAL_U32); - uint32_t exit_code = literal_u32.value.as_u32; + uint32_t n = literal_u32.value.as_u32; - fprintf(out, " mov $%d, %%eax\n", exit_code); + fprintf(out, " mov $%d, %%rax\n", n); return; } - case AST_NODE_BINARY_OP: + case AST_NODE_BINARY_OP: { + ast_binary_op_t bin_op = expr_node->data.as_bin_op; + switch (bin_op.kind) { + case AST_BINOP_ADDITION: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " add %%rcx, %%rax\n"); + + return; + } + case AST_BINOP_MULTIPLICATION: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " mul %%rcx\n"); + + return; + } + case AST_BINOP_DIVISION: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " div %%rcx\n"); + + return; + } + case AST_BINOP_REMINDER: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + fprintf(out, " xor %%edx, %%edx\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " div %%rcx\n"); + fprintf(out, " mov %%edx, %%eax\n"); + + return; + } + case AST_BINOP_SUBTRACTION: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " sub %%rcx, %%rax\n"); + + return; + } + case AST_BINOP_CMP_EQ: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " sete %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_CMP_LT: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " setl %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_CMP_GT: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " setg %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_CMP_NEQ: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " setne %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_CMP_LEQ: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " setle %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_CMP_GEQ: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " cmp %%rcx, %%rax\n"); + fprintf(out, " setge %%al\n"); + fprintf(out, " movzb %%al, %%rax\n"); + + return; + } + case AST_BINOP_BITWISE_LSHIFT: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " shl %%cl, %%rax\n"); + + return; + } + case AST_BINOP_BITWISE_RSHIFT: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " shr %%cl, %%rax\n"); + + return; + } + case AST_BINOP_BITWISE_XOR: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " xor %%ecx, %%eax\n"); + + return; + } + case AST_BINOP_BITWISE_AND: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " and %%ecx, %%eax\n"); + + return; + } + case AST_BINOP_BITWISE_OR: { + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " push %%rax\n"); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " pop %%rcx\n"); + fprintf(out, " or %%ecx, %%eax\n"); + + return; + } + case AST_BINOP_LOGICAL_AND: { + size_t label_exit = codegen_linux_x86_64_get_next_label(); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " cmp $0, %%rax\n"); + fprintf(out, " je .L%ld\n", label_exit); + + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " cmp $0, %%rax\n"); + fprintf(out, " je .L%ld\n", label_exit); + fprintf(out, " mov $1, %%rax\n"); + fprintf(out, ".L%ld:\n", label_exit); + + return; + } + case AST_BINOP_LOGICAL_OR: { + size_t label_t = codegen_linux_x86_64_get_next_label(); + size_t label_f = codegen_linux_x86_64_get_next_label(); + + codegen_linux_x86_64_emit_expression(out, bin_op.lhs); + fprintf(out, " cmp $0, %%rax\n"); + fprintf(out, " jne .L%ld\n", label_t); + + codegen_linux_x86_64_emit_expression(out, bin_op.rhs); + fprintf(out, " cmp $0, %%rax\n"); + fprintf(out, " je .L%ld\n", label_f); + + fprintf(out, ".L%ld:\n", label_t); + fprintf(out, " mov $1, %%rax\n"); + fprintf(out, ".L%ld:\n", label_f); + + return; + } + default: { + assert(0 && "unsupported binary operation"); + return; + } + } + } default: - assert(0 && "NOT IMPLEMENTED"); + assert(0 && "unsupported expression"); } } diff --git a/src/parser.c b/src/parser.c index 5ba5a3f..5dd4ef1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -152,7 +152,7 @@ get_binary_op_precedence(token_kind_t kind) case TOKEN_CMP_LEQ: case TOKEN_CMP_GEQ: return BINOP_CMP_RELATIONAL_PREC; - case TOKEN_EQ: + case TOKEN_CMP_EQ: case TOKEN_CMP_NEQ: return BINOP_CMP_EQUALITY_PREC; case TOKEN_AND: -- 2.44.0