From 39c96187c71d42399da2911dcfd0b48b34f41270 Mon Sep 17 00:00:00 2001 From: Yap Zhi Heng Date: Sun, 26 Oct 2025 10:49:28 +0800 Subject: [PATCH] gccrs: Add minus sign compilation for LiteralPattern GIMPLE output for literalpattern_neg.rs test case: ... x = -55; RUSTTMP.2 = x; if (RUSTTMP.2 == 55) goto ; else goto ; : { RUSTTMP.1 = 1; goto ; } : if (RUSTTMP.2 == -55) goto ; else goto ; : { RUSTTMP.1 = 0; goto ; } : if (1 != 0) goto ; else goto ; : { RUSTTMP.1 = 1; goto ; } ... gcc/rust/ChangeLog: * parse/rust-parse-impl.h (parse_literal_or_range_pattern): Parse minus sign properly for LiteralPattern. * ast/rust-pattern.h (LiteralPattern): Add has_minus boolean for LiteralPattern. * hir/tree/rust-hir-pattern.h (LiteralPattern): Ditto. * ast/rust-pattern.cc (LiteralPattern::as_string): Update to include minus sign if present. * hir/tree/rust-hir.cc (LiteralPattern::as_string): Ditto. * hir/rust-ast-lower-pattern.cc (visit(LiteralPattern)): Pass has_minus boolean from AST to HIR. * backend/rust-compile-pattern.cc (CompilePatternCheckExpr::visit(LiteralPattern)): Compile litexpr as negative if minus sign is present. Signed-off-by: Yap Zhi Heng --- gcc/rust/ast/rust-pattern.cc | 2 +- gcc/rust/ast/rust-pattern.h | 22 +++++++++++++++++-- gcc/rust/backend/rust-compile-pattern.cc | 2 ++ gcc/rust/hir/rust-ast-lower-pattern.cc | 3 ++- gcc/rust/hir/tree/rust-hir-pattern.h | 14 ++++++++++-- gcc/rust/hir/tree/rust-hir.cc | 2 +- gcc/rust/parse/rust-parse-impl.h | 2 +- .../execute/torture/literalpattern_neg.rs | 9 ++++++++ 8 files changed, 48 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/rust/execute/torture/literalpattern_neg.rs diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index a2fe5d59081..80189d3746b 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -48,7 +48,7 @@ tokenid_to_rangekind (TokenId id) std::string LiteralPattern::as_string () const { - return lit.as_string (); + return (has_minus ? "-" : "") + lit.as_string (); } std::string diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 0da1981928f..3b1bd1c29ec 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -30,6 +30,7 @@ class LiteralPattern : public Pattern Literal lit; location_t locus; NodeId node_id; + bool has_minus; public: std::string as_string () const override; @@ -37,17 +38,34 @@ class LiteralPattern : public Pattern // Constructor for a literal pattern LiteralPattern (Literal lit, location_t locus) : lit (std::move (lit)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (false) + {} + + LiteralPattern (Literal lit, location_t locus, bool has_minus) + : lit (std::move (lit)), locus (locus), + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (has_minus) {} LiteralPattern (std::string val, Literal::LitType type, location_t locus, PrimitiveCoreType type_hint) : lit (Literal (std::move (val), type, type_hint)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (false) + {} + + LiteralPattern (std::string val, Literal::LitType type, location_t locus, + PrimitiveCoreType type_hint, bool has_minus) + : lit (Literal (std::move (val), type, type_hint)), locus (locus), + node_id (Analysis::Mappings::get ().get_next_node_id ()), + has_minus (has_minus) {} location_t get_locus () const override final { return locus; } + bool get_has_minus () const { return has_minus; } + void accept_vis (ASTVisitor &vis) override; NodeId get_node_id () const override { return node_id; } diff --git a/gcc/rust/backend/rust-compile-pattern.cc b/gcc/rust/backend/rust-compile-pattern.cc index 82333dc39c0..3a983e9bc88 100644 --- a/gcc/rust/backend/rust-compile-pattern.cc +++ b/gcc/rust/backend/rust-compile-pattern.cc @@ -87,6 +87,8 @@ CompilePatternCheckExpr::visit (HIR::LiteralPattern &pattern) auto litexpr = std::make_unique ( HIR::LiteralExpr (pattern.get_mappings (), pattern.get_literal (), pattern.get_locus (), std::vector ())); + if (pattern.get_has_minus ()) + litexpr->set_negative (); // Note: Floating point literals are currently accepted but will likely be // forbidden in LiteralPatterns in a future version of Rust. diff --git a/gcc/rust/hir/rust-ast-lower-pattern.cc b/gcc/rust/hir/rust-ast-lower-pattern.cc index 4250adbfbab..c941a5c9af9 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.cc +++ b/gcc/rust/hir/rust-ast-lower-pattern.cc @@ -280,7 +280,8 @@ ASTLoweringPattern::visit (AST::LiteralPattern &pattern) HIR::Literal l = lower_literal (pattern.get_literal ()); translated - = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus ()); + = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (), + pattern.get_has_minus ()); } void diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h index 89b9cc6a06c..a2c408fdc77 100644 --- a/gcc/rust/hir/tree/rust-hir-pattern.h +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -32,19 +32,27 @@ class LiteralPattern : public Pattern Literal lit; location_t locus; Analysis::NodeMapping mappings; + bool has_minus; public: std::string as_string () const override; // Constructor for a literal pattern LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus) - : lit (std::move (lit)), locus (locus), mappings (mappings) + : lit (std::move (lit)), locus (locus), mappings (mappings), + has_minus (false) + {} + + LiteralPattern (Analysis::NodeMapping mappings, Literal lit, location_t locus, + bool has_minus) + : lit (std::move (lit)), locus (locus), mappings (mappings), + has_minus (has_minus) {} LiteralPattern (Analysis::NodeMapping mappings, std::string val, Literal::LitType type, location_t locus) : lit (Literal (std::move (val), type, PrimitiveCoreType::CORETYPE_STR)), - locus (locus), mappings (mappings) + locus (locus), mappings (mappings), has_minus (false) {} location_t get_locus () const override { return locus; } @@ -65,6 +73,8 @@ class LiteralPattern : public Pattern Literal &get_literal () { return lit; } const Literal &get_literal () const { return lit; } + bool get_has_minus () const { return has_minus; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc index ce10b02303c..57f560b06d3 100644 --- a/gcc/rust/hir/tree/rust-hir.cc +++ b/gcc/rust/hir/tree/rust-hir.cc @@ -2634,7 +2634,7 @@ StructPattern::as_string () const std::string LiteralPattern::as_string () const { - return lit.as_string (); + return (has_minus ? "-" : "") + lit.as_string (); } std::string diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index ec4c1c1d6c7..e7972770455 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -10345,7 +10345,7 @@ Parser::parse_literal_or_range_pattern () return std::unique_ptr ( new AST::LiteralPattern (range_lower->get_str (), type, range_lower->get_locus (), - range_lower->get_type_hint ())); + range_lower->get_type_hint (), has_minus)); } } diff --git a/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs b/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs new file mode 100644 index 00000000000..3553c4a3462 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/literalpattern_neg.rs @@ -0,0 +1,9 @@ +fn main() -> i32 { + let x = -55; + + match x { + 55 => 1, + -55 => 0, // correct case + _ => 1 + } +} \ No newline at end of file