https://gcc.gnu.org/g:a438e47eeddb5e56dbcb3387417f334a582b5764
commit r15-8343-ga438e47eeddb5e56dbcb3387417f334a582b5764 Author: badumbatish <tanghocle...@gmail.com> Date: Sun Jul 7 22:03:12 2024 -0700 gccrs: Refactor compile-asm for first round review gcc/rust/ChangeLog: * backend/rust-compile-asm.cc (strip_double_quotes): Refactor compile-asm for first round review (CompileAsm::asm_build_asm_stmt): Likewise. (CompileAsm::asm_build_expr): Likewise. (CompileAsm::asm_get_locus): Likewise. (CompileAsm::asm_construct_string_tree): Likewise. (CompileAsm::asm_construct_outputs): Likewise. (CompileAsm::asm_construct_inputs): Likewise. (CompileAsm::asm_construct_clobber_tree): Likewise. (CompileAsm::asm_construct_label_tree): Likewise. (CompileAsm::asm_is_simple): Likewise. (CompileAsm::asm_is_inline): Likewise. * backend/rust-compile-asm.h (strip_double_quotes): Likewise. (class CompileAsm): Likewise. Diff: --- gcc/rust/backend/rust-compile-asm.cc | 251 +++++++---------------------------- gcc/rust/backend/rust-compile-asm.h | 127 +++++++++--------- 2 files changed, 107 insertions(+), 271 deletions(-) diff --git a/gcc/rust/backend/rust-compile-asm.cc b/gcc/rust/backend/rust-compile-asm.cc index fe080f6aa6b9..8fd62dd48c9d 100644 --- a/gcc/rust/backend/rust-compile-asm.cc +++ b/gcc/rust/backend/rust-compile-asm.cc @@ -1,72 +1,57 @@ #include "rust-compile-asm.h" -#include "rust-tree.h" #include "rust-system.h" -#include <cstddef> namespace Rust { namespace Compile { +std::string +strip_double_quotes (const std::string &str) +{ + // Helper function strips the beginning and ending double quotes from a + // string. + std::string result = str; + + rust_assert (result.size () >= 3); + result.erase (0, 1); + result.erase (result.size () - 1, 1); + return result; +} + CompileAsm::CompileAsm (Context *ctx) : HIRCompileBase (ctx), translated (error_mark_node) {} void CompileAsm::visit (HIR::InlineAsm &expr) { - return ctx->add_statement (asm_build_expr (expr)); -} -tree -CompileAsm::asm_build_asm_stmt (HIR::InlineAsm &expr) -{ - // From the implementation of c-typeck.cc - // tree - // build_asm_stmt (bool is_volatile, tree args) - //{ - // if (is_volatile) - // ASM_VOLATILE_P (args) = 1; - // return add_stmt (args); - // } - // - return NULL_TREE; + ctx->add_statement (asm_build_expr (expr)); } + tree CompileAsm::asm_build_expr (HIR::InlineAsm &expr) { - auto asm_expr = asm_build_stmt (asm_get_locus (expr), ASM_EXPR, - {asm_construct_string_tree (expr), - asm_construct_outputs (expr), - asm_construct_inputs (expr), - asm_construct_clobber_tree (expr), - asm_construct_label_tree (expr)}); + auto asm_expr + = asm_build_stmt (expr.get_locus (), {asm_construct_string_tree (expr), + asm_construct_outputs (expr), + asm_construct_inputs (expr), + asm_construct_clobber_tree (expr), + asm_construct_label_tree (expr)}); ASM_BASIC_P (asm_expr) = CompileAsm::asm_is_simple (expr); - ASM_VOLATILE_P (asm_expr) = (false); + ASM_VOLATILE_P (asm_expr) = false; ASM_INLINE_P (asm_expr) = CompileAsm::asm_is_inline (expr); return asm_expr; - // return build_asm_expr (CompileAsm::asm_get_locus (expr), - // CompileAsm::asm_construct_string_tree (expr), - // CompileAsm::asm_construct_outputs (expr), - // CompileAsm::asm_construct_inputs (expr), - // CompileAsm::asm_construct_clobber_tree (expr), - // CompileAsm::asm_construct_label_tree (expr), - // CompileAsm::asm_is_simple (expr), - // CompileAsm::asm_is_inline (expr)); } tree CompileAsm::asm_build_stmt ( - location_t loc, enum tree_code code, + location_t loc, const std::array<tree, CompileAsm::ASM_TREE_ARRAY_LENGTH> &trees) { + // Prototype functiion for building an ASM_EXPR tree. tree ret; - // va_list p; bool side_effects; - /* This function cannot be used to construct variably-sized nodes. */ - gcc_assert (TREE_CODE_CLASS (code) != tcc_vl_exp); - - // va_start (p, code); - - ret = make_node (code); + ret = make_node (ASM_EXPR); TREE_TYPE (ret) = void_type_node; SET_EXPR_LOCATION (ret, loc); @@ -75,6 +60,8 @@ CompileAsm::asm_build_stmt ( expressions by checking whether the parameters have side effects. */ + // This is here because of c-typeck.cc's code + // I'm not sure what kind of effects it has side_effects = false; for (size_t i = 0; i < trees.size (); i++) { @@ -86,213 +73,65 @@ CompileAsm::asm_build_stmt ( TREE_SIDE_EFFECTS (ret) |= side_effects; - // va_end (p); return ret; } -location_t -CompileAsm::asm_get_locus (HIR::InlineAsm &expr) -{ - return expr.get_locus (); -} + tree CompileAsm::asm_construct_string_tree (HIR::InlineAsm &expr) { - if (expr.template_strs.empty ()) - return build_string (1, ""); - else - return build_string (4, "nop"); - // Initialize to NULL_TREE - tree string_chain = NULL_TREE; - + // To construct an ASM_EXPR tree, we need to build a STRING_CST tree. + // + // We do this by concatenating all the template strings in the InlineAsm + // into one big std::string seperated by tabs and newlines. (For easier + // debugging and reading) + std::stringstream ss; for (const auto &template_str : expr.template_strs) - { - auto str = template_str.symbol; - auto string_tree = build_string (str.size () + 1, str.c_str ()); - - string_chain = tree_cons (NULL_TREE, string_tree, string_chain); - } - // Reverse the chain before returning + ss << strip_double_quotes (template_str.symbol) << "\n\t"; - string_chain = nreverse (string_chain); - - return nreverse (string_chain); + std::string result = ss.str (); + return build_string (result.size () + 1, result.c_str ()); } + tree CompileAsm::asm_construct_outputs (HIR::InlineAsm &expr) { + // TODO: Do i need to do this? return NULL_TREE; } tree CompileAsm::asm_construct_inputs (HIR::InlineAsm &expr) { + // TODO: Do i need to do this? return NULL_TREE; } tree CompileAsm::asm_construct_clobber_tree (HIR::InlineAsm &expr) { + // TODO: Do i need to do this? return NULL_TREE; } + tree CompileAsm::asm_construct_label_tree (HIR::InlineAsm &expr) { + // TODO: Do i need to do this? return NULL_TREE; } bool CompileAsm::asm_is_simple (HIR::InlineAsm &expr) { + // TODO: Check back later to determine how an InlineAsm is simple. return true; } bool CompileAsm::asm_is_inline (HIR::InlineAsm &expr) { + // TODO: Check back later to determine how an InlineAsm is inline. return true; } } // namespace Compile } // namespace Rust - // - // - // The following section serves as documentation for PR revieweres and future - // asm developers. It documents the inspriation for the implementation of the - // CompileAsm class - -// From the implementation of c-typeck.cc -// tree -// build_asm_stmt (bool is_volatile, tree args) -//{ -// if (is_volatile) -// ASM_VOLATILE_P (args) = 1; -// return add_stmt (args); -// } -// -///* Build an asm-expr, whose components are a STRING, some OUTPUTS, -// some INPUTS, and some CLOBBERS. The latter three may be NULL. -// SIMPLE indicates whether there was anything at all after the -// string in the asm expression -- asm("blah") and asm("blah" : ) -// are subtly different. We use a ASM_EXPR node to represent this. -// LOC is the location of the asm, and IS_INLINE says whether this -// is asm inline. */ -// tree -// build_asm_expr (location_t loc, tree string, tree outputs, tree inputs, -// tree clobbers, tree labels, bool simple, bool is_inline) -//{ -// tree tail; -// tree args; -// int i; -// const char *constraint; -// const char **oconstraints; -// bool allows_mem, allows_reg, is_inout; -// int ninputs, noutputs; -// -// ninputs = list_length (inputs); -// noutputs = list_length (outputs); -// oconstraints = (const char **) alloca (noutputs * sizeof (const char *)); -// -// string = resolve_asm_operand_names (string, outputs, inputs, labels); -// -// /* Remove output conversions that change the type but not the mode. */ -// for (i = 0, tail = outputs; tail; ++i, tail = TREE_CHAIN (tail)) -// { -// tree output = TREE_VALUE (tail); -// -// output = c_fully_fold (output, false, NULL, true); -// -// /* ??? Really, this should not be here. Users should be using a -// proper lvalue, dammit. But there's a long history of using casts -// in the output operands. In cases like longlong.h, this becomes a -// primitive form of typechecking -- if the cast can be removed, then -// the output operand had a type of the proper width; otherwise we'll -// get an error. Gross, but ... */ -// STRIP_NOPS (output); -// -// if (!lvalue_or_else (loc, output, lv_asm)) -// output = error_mark_node; -// -// if (output != error_mark_node -// && (TREE_READONLY (output) -// || TYPE_READONLY (TREE_TYPE (output)) -// || (RECORD_OR_UNION_TYPE_P (TREE_TYPE (output)) -// && C_TYPE_FIELDS_READONLY (TREE_TYPE (output))))) -// readonly_error (loc, output, lv_asm); -// -// constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); -// oconstraints[i] = constraint; -// -// if (parse_output_constraint (&constraint, i, ninputs, noutputs, -// &allows_mem, &allows_reg, &is_inout)) -// { -// /* If the operand is going to end up in memory, -// mark it addressable. */ -// if (!allows_reg && !c_mark_addressable (output)) -// output = error_mark_node; -// if (!(!allows_reg && allows_mem) -// && output != error_mark_node -// && VOID_TYPE_P (TREE_TYPE (output))) -// { -// error_at (loc, "invalid use of void expression"); -// output = error_mark_node; -// } -// } -// else -// output = error_mark_node; -// -// TREE_VALUE (tail) = output; -// } -// -// for (i = 0, tail = inputs; tail; ++i, tail = TREE_CHAIN (tail)) -// { -// tree input; -// -// constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (tail))); -// input = TREE_VALUE (tail); -// -// if (parse_input_constraint (&constraint, i, ninputs, noutputs, 0, -// oconstraints, &allows_mem, &allows_reg)) -// { -// /* If the operand is going to end up in memory, -// mark it addressable. */ -// if (!allows_reg && allows_mem) -// { -// input = c_fully_fold (input, false, NULL, true); -// -// /* Strip the nops as we allow this case. FIXME, this really -// should be rejected or made deprecated. */ -// STRIP_NOPS (input); -// if (!c_mark_addressable (input)) -// input = error_mark_node; -// } -// else -// { -// struct c_expr expr; -// memset (&expr, 0, sizeof (expr)); -// expr.value = input; -// expr = convert_lvalue_to_rvalue (loc, expr, true, false); -// input = c_fully_fold (expr.value, false, NULL); -// -// if (input != error_mark_node && VOID_TYPE_P (TREE_TYPE (input))) -// { -// error_at (loc, "invalid use of void expression"); -// input = error_mark_node; -// } -// } -// } -// else -// input = error_mark_node; -// -// TREE_VALUE (tail) = input; -// } -// -// args = build_stmt (loc, ASM_EXPR, string, outputs, inputs, clobbers, -// labels); -// -// /* asm statements without outputs, including simple ones, are treated -// as volatile. */ -// ASM_INPUT_P (args) = simple; -// ASM_VOLATILE_P (args) = (noutputs == 0); -// ASM_INLINE_P (args) = is_inline; -// -// return args; -//} diff --git a/gcc/rust/backend/rust-compile-asm.h b/gcc/rust/backend/rust-compile-asm.h index d7967bc7fdb5..15ffc707986f 100644 --- a/gcc/rust/backend/rust-compile-asm.h +++ b/gcc/rust/backend/rust-compile-asm.h @@ -26,78 +26,25 @@ namespace Rust { namespace Compile { +std::string +strip_double_quotes (const std::string &); + class CompileAsm : private HIRCompileBase, protected HIR::HIRExpressionVisitor { +private: + tree translated; + public: + // WE WILL OPEN THIS UP WHEN WE WANT TO ADD A DEDICATED PASS OF HIR'S ASM + // translation. // static tree Compile (HIR::Expr *expr, Context *ctx); - void visit (HIR::InlineAsm &expr) override; - - void visit (HIR::TupleIndexExpr &expr) override {} - void visit (HIR::TupleExpr &expr) override {} - void visit (HIR::ReturnExpr &expr) override {} - void visit (HIR::CallExpr &expr) override {} - void visit (HIR::MethodCallExpr &expr) override {} - void visit (HIR::LiteralExpr &expr) override {} - void visit (HIR::AssignmentExpr &expr) override {} - void visit (HIR::CompoundAssignmentExpr &expr) override {} - void visit (HIR::ArrayIndexExpr &expr) override {} - void visit (HIR::ArrayExpr &expr) override {} - void visit (HIR::ArithmeticOrLogicalExpr &expr) override {} - void visit (HIR::ComparisonExpr &expr) override {} - void visit (HIR::LazyBooleanExpr &expr) override {} - void visit (HIR::NegationExpr &expr) override {} - void visit (HIR::TypeCastExpr &expr) override {} - void visit (HIR::IfExpr &expr) override {} - void visit (HIR::IfExprConseqElse &expr) override {} - void visit (HIR::BlockExpr &expr) override {} - void visit (HIR::UnsafeBlockExpr &expr) override {} - void visit (HIR::StructExprStruct &struct_expr) override {} - void visit (HIR::StructExprStructFields &struct_expr) override {} - void visit (HIR::GroupedExpr &expr) override {} - void visit (HIR::FieldAccessExpr &expr) override {} - void visit (HIR::QualifiedPathInExpression &expr) override {} - void visit (HIR::PathInExpression &expr) override {} - void visit (HIR::LoopExpr &expr) override {} - void visit (HIR::WhileLoopExpr &expr) override {} - void visit (HIR::BreakExpr &expr) override {} - void visit (HIR::ContinueExpr &expr) override {} - void visit (HIR::BorrowExpr &expr) override {} - void visit (HIR::DereferenceExpr &expr) override {} - void visit (HIR::MatchExpr &expr) override {} - void visit (HIR::RangeFromToExpr &expr) override {} - void visit (HIR::RangeFromExpr &expr) override {} - void visit (HIR::RangeToExpr &expr) override {} - void visit (HIR::RangeFullExpr &expr) override {} - void visit (HIR::RangeFromToInclExpr &expr) override {} - void visit (HIR::ClosureExpr &expr) override {} - - // TODO - void visit (HIR::ErrorPropagationExpr &) override {} - void visit (HIR::RangeToInclExpr &) override {} - - // TODO - // these need to be sugared in the HIR to if statements and a match - void visit (HIR::WhileLetLoopExpr &) override {} - void visit (HIR::IfLetExpr &) override {} - void visit (HIR::IfLetExprConseqElse &) override {} - - // lets not worry about async yet.... - void visit (HIR::AwaitExpr &) override {} - void visit (HIR::AsyncBlockExpr &) override {} - - // nothing to do for these - void visit (HIR::StructExprFieldIdentifier &) override {} - void visit (HIR::StructExprFieldIdentifierValue &) override {} - void visit (HIR::StructExprFieldIndexValue &) override {} - + // RELEVANT MEMBER FUNCTIONS static const int ASM_TREE_ARRAY_LENGTH = 5; - static tree asm_build_asm_stmt (HIR::InlineAsm &); static tree asm_build_expr (HIR::InlineAsm &); - static tree asm_build_stmt (location_t, enum tree_code, + static tree asm_build_stmt (location_t, const std::array<tree, ASM_TREE_ARRAY_LENGTH> &); - static location_t asm_get_locus (HIR::InlineAsm &); static tree asm_construct_string_tree (HIR::InlineAsm &); static tree asm_construct_outputs (HIR::InlineAsm &); static tree asm_construct_inputs (HIR::InlineAsm &); @@ -108,8 +55,58 @@ public: CompileAsm (Context *ctx); -private: - tree translated; + void visit (HIR::InlineAsm &) override; + + // NON RELEVANT MEMBER FUNCTIONS + + void visit (HIR::TupleIndexExpr &) override {} + void visit (HIR::TupleExpr &) override {} + void visit (HIR::ReturnExpr &) override {} + void visit (HIR::CallExpr &) override {} + void visit (HIR::MethodCallExpr &) override {} + void visit (HIR::LiteralExpr &) override {} + void visit (HIR::AssignmentExpr &) override {} + void visit (HIR::CompoundAssignmentExpr &) override {} + void visit (HIR::ArrayIndexExpr &) override {} + void visit (HIR::ArrayExpr &) override {} + void visit (HIR::ArithmeticOrLogicalExpr &) override {} + void visit (HIR::ComparisonExpr &) override {} + void visit (HIR::LazyBooleanExpr &) override {} + void visit (HIR::NegationExpr &) override {} + void visit (HIR::TypeCastExpr &) override {} + void visit (HIR::IfExpr &) override {} + void visit (HIR::IfExprConseqElse &) override {} + void visit (HIR::BlockExpr &) override {} + void visit (HIR::UnsafeBlockExpr &) override {} + void visit (HIR::StructExprStruct &struct_) override {} + void visit (HIR::StructExprStructFields &struct_) override {} + void visit (HIR::GroupedExpr &) override {} + void visit (HIR::FieldAccessExpr &) override {} + void visit (HIR::QualifiedPathInExpression &) override {} + void visit (HIR::PathInExpression &) override {} + void visit (HIR::LoopExpr &) override {} + void visit (HIR::WhileLoopExpr &) override {} + void visit (HIR::BreakExpr &) override {} + void visit (HIR::ContinueExpr &) override {} + void visit (HIR::BorrowExpr &) override {} + void visit (HIR::DereferenceExpr &) override {} + void visit (HIR::MatchExpr &) override {} + void visit (HIR::RangeFromToExpr &) override {} + void visit (HIR::RangeFromExpr &) override {} + void visit (HIR::RangeToExpr &) override {} + void visit (HIR::RangeFullExpr &) override {} + void visit (HIR::RangeFromToInclExpr &) override {} + void visit (HIR::ClosureExpr &) override {} + void visit (HIR::ErrorPropagationExpr &) override {} + void visit (HIR::RangeToInclExpr &) override {} + void visit (HIR::WhileLetLoopExpr &) override {} + void visit (HIR::IfLetExpr &) override {} + void visit (HIR::IfLetExprConseqElse &) override {} + void visit (HIR::AwaitExpr &) override {} + void visit (HIR::AsyncBlockExpr &) override {} + void visit (HIR::StructExprFieldIdentifier &) override {} + void visit (HIR::StructExprFieldIdentifierValue &) override {} + void visit (HIR::StructExprFieldIndexValue &) override {} }; } // namespace Compile } // namespace Rust