#include "rust-macro.h"
#include "rust-operators.h"
#include "rust-system.h"
+#include <memory>
namespace Rust {
namespace AST {
SplitInOut,
Const,
Sym,
+ Label,
};
struct In
return *this;
}
};
+
+ struct Label
+ {
+ std::string label_name;
+ std::unique_ptr<Expr> expr;
+
+ Label () {}
+
+ Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr)
+ : expr (std::move (expr))
+ {
+ if (label_name.has_value ())
+ this->label_name = label_name.value ();
+ }
+ Label (const struct Label &other)
+ {
+ if (other.expr)
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ }
+
+ Label operator= (const struct Label &other)
+ {
+ if (other.expr)
+ expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+ return *this;
+ }
+ };
+
RegisterType register_type;
struct In in;
struct SplitInOut split_in_out;
struct Const cnst;
struct Sym sym;
+ struct Label label;
InlineAsmOperand () {}
InlineAsmOperand (const InlineAsmOperand &other)
this->sym = reg.value ();
}
+ void set_label (const tl::optional<struct Label> ®)
+ {
+ this->register_type = Label;
+ if (reg.has_value ())
+ this->label = reg.value ();
+ }
+
location_t locus;
};
}
else if (parser.peek_current_token ()->get_id () == CONST)
{
- // TODO: Please handle const
- rust_unreachable ();
- return tl::nullopt;
+ // TODO: Please handle const with parse_expr instead.
+ auto anon_const
+ = parse_format_string (parser, last_token_id, inline_asm_ctx);
+ reg_operand.set_cnst (tl::nullopt);
+ return reg_operand;
}
- else if (false && check_identifier (parser, "sym"))
+ else if (check_identifier (parser, "sym"))
{
- // TODO: Please handle sym
+ // TODO: Please handle sym, which needs ExprKind::Path in Rust's asm.rs
rust_unreachable ();
return tl::nullopt;
}
- else if (false && check_identifier (parser, "label"))
+ else if (auto label_str = parse_label (parser, last_token_id, inline_asm_ctx))
+ {
+ auto block = parser.parse_block_expr ();
+ struct AST::InlineAsmOperand::Label label (label_str,
+ block ? block->clone_expr ()
+ : nullptr);
+ reg_operand.set_label (label);
+ return reg_operand;
+ }
+ else if (inline_asm_ctx.allows_templates ())
{
- // TODO: Please handle label
+ // TODO: If we allow templating, do sth here
rust_unreachable ();
return tl::nullopt;
}
return fragment_ast;
}
+tl::optional<std::string>
+parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
+ InlineAsmContext &inline_asm_ctx)
+{
+ auto token = parser.peek_current_token ();
+
+ if (token->get_id () != last_token_id && token->get_id () == STRING_LITERAL)
+ {
+ // very nice, we got a string.
+ auto label = token->as_string ();
+
+ bool flag = true;
+ if (label.empty () || label.back () != ':')
+ flag = false; // Check if string is empty or does not end with a colon
+
+ // Check if all characters before the last colon are digits
+ for (int i = 0; i < label.length () - 1 && flag == true; i++)
+ {
+ if (label[i] < '0' || label[i] > '9')
+ flag = false;
+ }
+
+ if (flag == true)
+ {
+ parser.skip_token ();
+ return token->as_string ();
+ }
+ else
+ {
+ return tl::nullopt;
+ }
+ }
+ else
+ {
+ return tl::nullopt;
+ }
+}
} // namespace Rust
parse_format_string (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
InlineAsmContext &inline_asm_ctx);
+tl::optional<std::string>
+parse_label (Parser<MacroInvocLexer> &parser, TokenId last_token_id,
+ InlineAsmContext &inline_asm_ctx);
+
std::set<std::string> potentially_nonpromoted_keywords
= {"in", "out", "lateout", "inout", "inlateout", "const", "sym", "label"};