Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve InlineAsmOperand #3193

Merged
merged 1 commit into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading