Skip to content

Commit

Permalink
Rework InlineAsmOperand
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
powerboat9 authored and P-E-P committed Oct 13, 2024
1 parent 3bff5cf commit 583eb22
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 36 deletions.
183 changes: 148 additions & 35 deletions gcc/rust/ast/rust-expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -4771,7 +4771,7 @@ struct InlineAsmRegOrRegClass
class InlineAsmOperand
{
public:
enum RegisterType
enum class RegisterType
{
In,
Out,
Expand All @@ -4782,8 +4782,24 @@ class InlineAsmOperand
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;

Expand All @@ -4808,10 +4824,14 @@ class InlineAsmOperand

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
Expand All @@ -4837,10 +4857,14 @@ class InlineAsmOperand
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
Expand All @@ -4867,10 +4891,14 @@ class InlineAsmOperand

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;
Expand Down Expand Up @@ -4902,15 +4930,23 @@ class InlineAsmOperand

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))
Expand All @@ -4927,10 +4963,14 @@ class InlineAsmOperand
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;

Expand All @@ -4951,27 +4991,37 @@ class InlineAsmOperand
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 &reg) : register_type (In), in (reg) {}
InlineAsmOperand (const struct Out &reg) : register_type (Out), out (reg) {}
InlineAsmOperand (const struct InOut &reg)
: register_type (InOut), in_out (reg)
InlineAsmOperand (const In &reg, location_t locus)
: register_type (RegisterType::In), locus (locus), reg (new In (reg))
{}
InlineAsmOperand (const Out &reg, location_t locus)
: register_type (RegisterType::Out), locus (locus), reg (new Out (reg))
{}
InlineAsmOperand (const InOut &reg, location_t locus)
: register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg))
{}
InlineAsmOperand (const SplitInOut &reg, location_t locus)
: register_type (RegisterType::SplitInOut), locus (locus),
reg (new SplitInOut (reg))
{}
InlineAsmOperand (const struct SplitInOut &reg)
: register_type (SplitInOut), split_in_out (reg)
InlineAsmOperand (const Const &reg, location_t locus)
: register_type (RegisterType::Const), locus (locus), reg (new Const (reg))
{}
InlineAsmOperand (const struct Const &reg) : register_type (Const), cnst (reg)
InlineAsmOperand (const Sym &reg, location_t locus)
: register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg))
{}
InlineAsmOperand (const struct Sym &reg) : register_type (Sym), sym (reg) {}
InlineAsmOperand (const struct Label &reg)
: register_type (Label), label (reg)
InlineAsmOperand (const Label &reg, location_t locus)
: register_type (RegisterType::Label), locus (locus), reg (new Label (reg))
{}

location_t get_locus () const { return locus; }
Expand All @@ -4980,25 +5030,88 @@ class InlineAsmOperand
// 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
Expand Down
3 changes: 2 additions & 1 deletion gcc/rust/expand/rust-macro-builtins-asm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
Expand Down

0 comments on commit 583eb22

Please sign in to comment.