From: Owen Avery <powerboat9.ga...@gmail.com> Not thrilled with some of this boilerplate, but it does seem like an improvement.
gcc/rust/ChangeLog: * ast/rust-expr.h (InlineAsmOperand): Replace multiple mutually-exclusive tl::optional fields with a std::unique_ptr and modify nested classes to allow this. Also, make getters return references where possible. * expand/rust-macro-builtins-asm.cc (parse_reg_operand_out): Pass location when constructing InlineAsmOperand. Signed-off-by: Owen Avery <powerboat9.ga...@gmail.com> --- gcc/rust/ast/rust-expr.h | 183 +++++++++++++++++---- gcc/rust/expand/rust-macro-builtins-asm.cc | 3 +- 2 files changed, 150 insertions(+), 36 deletions(-) diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 749fdc05f2b..438d3d3b86e 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -4771,7 +4771,7 @@ struct InlineAsmRegOrRegClass class InlineAsmOperand { public: - enum RegisterType + enum class RegisterType { In, Out, @@ -4782,8 +4782,24 @@ public: Label, }; - struct In + class Register { + public: + Register () {} + virtual ~Register () = default; + + std::unique_ptr<Register> clone () const + { + return std::unique_ptr<Register> (clone_impl ()); + } + + protected: + virtual Register *clone_impl () const = 0; + }; + + class In : public Register + { + public: tl::optional<InlineAsmRegOrRegClass> reg; std::unique_ptr<Expr> expr; @@ -4808,10 +4824,14 @@ public: return *this; } + + private: + In *clone_impl () const { return new In (*this); } }; - struct Out + class Out : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // can be null @@ -4837,10 +4857,14 @@ public: expr = other.expr->clone_expr (); return *this; } + + private: + Out *clone_impl () const { return new Out (*this); } }; - struct InOut + class InOut : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // this can't be null @@ -4867,10 +4891,14 @@ public: return *this; } + + private: + InOut *clone_impl () const { return new InOut (*this); } }; - struct SplitInOut + class SplitInOut : public Register { + public: tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> in_expr; @@ -4902,15 +4930,23 @@ public: return *this; } + + private: + SplitInOut *clone_impl () const { return new SplitInOut (*this); } }; - struct Const + class Const : public Register { + public: AnonConst anon_const; + + private: + Const *clone_impl () const { return new Const (*this); } }; - struct Sym + class Sym : public Register { + public: std::unique_ptr<Expr> expr; Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr)) @@ -4927,10 +4963,14 @@ public: expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; } + + private: + Sym *clone_impl () const { return new Sym (*this); } }; - struct Label + class Label : public Register { + public: std::string label_name; std::unique_ptr<Expr> expr; @@ -4951,27 +4991,37 @@ public: expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; } + + private: + Label *clone_impl () const { return new Label (*this); } }; InlineAsmOperand (const InlineAsmOperand &other) - : register_type (other.register_type), in (other.in), out (other.out), - in_out (other.in_out), split_in_out (other.split_in_out), - cnst (other.cnst), sym (other.sym) + : register_type (other.register_type), locus (other.locus), + reg (other.reg->clone ()) {} - InlineAsmOperand (const struct In ®) : register_type (In), in (reg) {} - InlineAsmOperand (const struct Out ®) : register_type (Out), out (reg) {} - InlineAsmOperand (const struct InOut ®) - : register_type (InOut), in_out (reg) + InlineAsmOperand (const In ®, location_t locus) + : register_type (RegisterType::In), locus (locus), reg (new In (reg)) + {} + InlineAsmOperand (const Out ®, location_t locus) + : register_type (RegisterType::Out), locus (locus), reg (new Out (reg)) + {} + InlineAsmOperand (const InOut ®, location_t locus) + : register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg)) + {} + InlineAsmOperand (const SplitInOut ®, location_t locus) + : register_type (RegisterType::SplitInOut), locus (locus), + reg (new SplitInOut (reg)) {} - InlineAsmOperand (const struct SplitInOut ®) - : register_type (SplitInOut), split_in_out (reg) + InlineAsmOperand (const Const ®, location_t locus) + : register_type (RegisterType::Const), locus (locus), reg (new Const (reg)) {} - InlineAsmOperand (const struct Const ®) : register_type (Const), cnst (reg) + InlineAsmOperand (const Sym ®, location_t locus) + : register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg)) {} - InlineAsmOperand (const struct Sym ®) : register_type (Sym), sym (reg) {} - InlineAsmOperand (const struct Label ®) - : register_type (Label), label (reg) + InlineAsmOperand (const Label ®, location_t locus) + : register_type (RegisterType::Label), locus (locus), reg (new Label (reg)) {} location_t get_locus () const { return locus; } @@ -4980,25 +5030,88 @@ public: // Potentially fail immediately if you don't use get_register_type() to // inspect the RegisterType first before calling the following functions Check // first - struct In get_in () const { return in.value (); } - struct Out get_out () const { return out.value (); } - struct InOut get_in_out () const { return in_out.value (); } - struct SplitInOut get_split_in_out () const { return split_in_out.value (); } - struct Const get_const () const { return cnst.value (); } - struct Sym get_sym () const { return sym.value (); } - struct Label get_label () const { return label.value (); } + In &get_in () + { + rust_assert (register_type == RegisterType::In); + return static_cast<In &> (*reg); + } + const In &get_in () const + { + rust_assert (register_type == RegisterType::In); + return static_cast<const In &> (*reg); + } + + Out &get_out () + { + rust_assert (register_type == RegisterType::Out); + return static_cast<Out &> (*reg); + } + const Out &get_out () const + { + rust_assert (register_type == RegisterType::Out); + return static_cast<const Out &> (*reg); + } + + InOut &get_in_out () + { + rust_assert (register_type == RegisterType::InOut); + return static_cast<InOut &> (*reg); + } + const InOut &get_in_out () const + { + rust_assert (register_type == RegisterType::InOut); + return static_cast<const InOut &> (*reg); + } + + SplitInOut &get_split_in_out () + { + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<SplitInOut &> (*reg); + } + const SplitInOut &get_split_in_out () const + { + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<const SplitInOut &> (*reg); + } + + Const &get_const () + { + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); + } + const Const &get_const () const + { + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); + } + + Sym &get_sym () + { + rust_assert (register_type == RegisterType::Sym); + return static_cast<Sym &> (*reg); + } + const Sym &get_sym () const + { + rust_assert (register_type == RegisterType::Sym); + return static_cast<const Sym &> (*reg); + } + + Label &get_label () + { + rust_assert (register_type == RegisterType::Label); + return static_cast<Label &> (*reg); + } + const Label &get_label () const + { + rust_assert (register_type == RegisterType::Label); + return static_cast<const Label &> (*reg); + } private: RegisterType register_type; location_t locus; - tl::optional<struct In> in; - tl::optional<struct Out> out; - tl::optional<struct InOut> in_out; - tl::optional<struct SplitInOut> split_in_out; - tl::optional<struct Const> cnst; - tl::optional<struct Sym> sym; - tl::optional<struct Label> label; + std::unique_ptr<Register> reg; }; struct InlineAsmPlaceHolder diff --git a/gcc/rust/expand/rust-macro-builtins-asm.cc b/gcc/rust/expand/rust-macro-builtins-asm.cc index 52dba1570c8..1017d9fd6c4 100644 --- a/gcc/rust/expand/rust-macro-builtins-asm.cc +++ b/gcc/rust/expand/rust-macro-builtins-asm.cc @@ -341,6 +341,7 @@ tl::expected<InlineAsmContext, InlineAsmParseError> parse_reg_operand_out (InlineAsmContext inline_asm_ctx) { auto &parser = inline_asm_ctx.parser; + location_t locus = parser.peek_current_token ()->get_locus (); if (!inline_asm_ctx.is_global_asm () && check_identifier (parser, "out")) { auto reg = parse_reg (inline_asm_ctx); @@ -355,7 +356,7 @@ parse_reg_operand_out (InlineAsmContext inline_asm_ctx) // instead of nullptr struct AST::InlineAsmOperand::Out out (reg, false, std::move (expr)); - inline_asm_ctx.inline_asm.operands.push_back (out); + inline_asm_ctx.inline_asm.operands.emplace_back (out, locus); return inline_asm_ctx; } -- 2.45.2