mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 20:01:22 -05:00
gccrs: Add HIR to GCC GENERIC lowering for all nodes
This patch implements the lowering mentioned in the previous patch for all HIR nodes. gcc/rust/ * backend/rust-compile-block.cc: New. * backend/rust-compile-block.h: New. * backend/rust-compile-expr.cc: New. * backend/rust-compile-expr.h: New. * backend/rust-compile-extern.h: New. * backend/rust-compile-fnparam.cc: New. * backend/rust-compile-fnparam.h: New. * backend/rust-compile-implitem.cc: New. * backend/rust-compile-implitem.h: New. * backend/rust-compile-intrinsic.cc: New. * backend/rust-compile-intrinsic.h: New. * backend/rust-compile-item.cc: New. * backend/rust-compile-item.h: New. * backend/rust-compile-pattern.cc: New. * backend/rust-compile-pattern.h: New. * backend/rust-compile-resolve-path.cc: New. * backend/rust-compile-resolve-path.h: New. * backend/rust-compile-stmt.cc: New. * backend/rust-compile-stmt.h: New. * backend/rust-compile-struct-field-expr.cc: New. * backend/rust-compile-struct-field-expr.h: New. * backend/rust-compile-type.cc: New. * backend/rust-compile-type.h: New. * backend/rust-compile-var-decl.h: New. Co-authored-by: David Faust <david.faust@oracle.com>
This commit is contained in:
committed by
Arthur Cohen
parent
15f04af347
commit
019b2f1558
158
gcc/rust/backend/rust-compile-block.cc
Normal file
158
gcc/rust/backend/rust-compile-block.cc
Normal file
@@ -0,0 +1,158 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-block.h"
|
||||
#include "rust-compile-stmt.h"
|
||||
#include "rust-compile-expr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
CompileBlock::CompileBlock (Context *ctx, Bvariable *result)
|
||||
: HIRCompileBase (ctx), translated (nullptr), result (result)
|
||||
{}
|
||||
|
||||
tree
|
||||
CompileBlock::compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result)
|
||||
{
|
||||
CompileBlock compiler (ctx, result);
|
||||
compiler.visit (*expr);
|
||||
return compiler.translated;
|
||||
}
|
||||
|
||||
void
|
||||
CompileBlock::visit (HIR::BlockExpr &expr)
|
||||
{
|
||||
fncontext fnctx = ctx->peek_fn ();
|
||||
tree fndecl = fnctx.fndecl;
|
||||
Location start_location = expr.get_locus ();
|
||||
Location end_location = expr.get_end_locus ();
|
||||
auto body_mappings = expr.get_mappings ();
|
||||
|
||||
Resolver::Rib *rib = nullptr;
|
||||
if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), &rib))
|
||||
{
|
||||
rust_fatal_error (expr.get_locus (), "failed to setup locals per block");
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<Bvariable *> locals
|
||||
= compile_locals_for_block (ctx, *rib, fndecl);
|
||||
|
||||
tree enclosing_scope = ctx->peek_enclosing_scope ();
|
||||
tree new_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals,
|
||||
start_location, end_location);
|
||||
ctx->push_block (new_block);
|
||||
|
||||
for (auto &s : expr.get_statements ())
|
||||
{
|
||||
auto compiled_expr = CompileStmt::Compile (s.get (), ctx);
|
||||
if (compiled_expr != nullptr)
|
||||
{
|
||||
tree s = convert_to_void (compiled_expr, ICV_STATEMENT);
|
||||
ctx->add_statement (s);
|
||||
}
|
||||
}
|
||||
|
||||
if (expr.has_expr ())
|
||||
{
|
||||
// the previous passes will ensure this is a valid return or
|
||||
// a valid trailing expression
|
||||
tree compiled_expr = CompileExpr::Compile (expr.expr.get (), ctx);
|
||||
if (compiled_expr != nullptr)
|
||||
{
|
||||
if (result == nullptr)
|
||||
{
|
||||
ctx->add_statement (compiled_expr);
|
||||
}
|
||||
else
|
||||
{
|
||||
tree result_reference = ctx->get_backend ()->var_expression (
|
||||
result, expr.get_final_expr ()->get_locus ());
|
||||
|
||||
tree assignment
|
||||
= ctx->get_backend ()->assignment_statement (result_reference,
|
||||
compiled_expr,
|
||||
expr.get_locus ());
|
||||
ctx->add_statement (assignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ctx->pop_block ();
|
||||
translated = new_block;
|
||||
}
|
||||
|
||||
void
|
||||
CompileConditionalBlocks::visit (HIR::IfExpr &expr)
|
||||
{
|
||||
fncontext fnctx = ctx->peek_fn ();
|
||||
tree fndecl = fnctx.fndecl;
|
||||
tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx);
|
||||
tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result);
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block,
|
||||
NULL, expr.get_locus ());
|
||||
}
|
||||
|
||||
void
|
||||
CompileConditionalBlocks::visit (HIR::IfExprConseqElse &expr)
|
||||
{
|
||||
fncontext fnctx = ctx->peek_fn ();
|
||||
tree fndecl = fnctx.fndecl;
|
||||
tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx);
|
||||
tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result);
|
||||
tree else_block = CompileBlock::compile (expr.get_else_block (), ctx, result);
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block,
|
||||
else_block, expr.get_locus ());
|
||||
}
|
||||
|
||||
void
|
||||
CompileConditionalBlocks::visit (HIR::IfExprConseqIf &expr)
|
||||
{
|
||||
fncontext fnctx = ctx->peek_fn ();
|
||||
tree fndecl = fnctx.fndecl;
|
||||
tree condition_expr = CompileExpr::Compile (expr.get_if_condition (), ctx);
|
||||
tree then_block = CompileBlock::compile (expr.get_if_block (), ctx, result);
|
||||
|
||||
// else block
|
||||
std::vector<Bvariable *> locals;
|
||||
Location start_location = expr.get_conseq_if_expr ()->get_locus ();
|
||||
Location end_location = expr.get_conseq_if_expr ()->get_locus (); // FIXME
|
||||
tree enclosing_scope = ctx->peek_enclosing_scope ();
|
||||
tree else_block = ctx->get_backend ()->block (fndecl, enclosing_scope, locals,
|
||||
start_location, end_location);
|
||||
ctx->push_block (else_block);
|
||||
|
||||
tree else_stmt_decl
|
||||
= CompileConditionalBlocks::compile (expr.get_conseq_if_expr (), ctx,
|
||||
result);
|
||||
ctx->add_statement (else_stmt_decl);
|
||||
|
||||
ctx->pop_block ();
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->if_statement (fndecl, condition_expr, then_block,
|
||||
else_block, expr.get_locus ());
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
211
gcc/rust/backend/rust-compile-block.h
Normal file
211
gcc/rust/backend/rust-compile-block.h
Normal file
@@ -0,0 +1,211 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_BLOCK
|
||||
#define RUST_COMPILE_BLOCK
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileBlock : private HIRCompileBase
|
||||
{
|
||||
public:
|
||||
static tree compile (HIR::BlockExpr *expr, Context *ctx, Bvariable *result);
|
||||
|
||||
protected:
|
||||
void visit (HIR::BlockExpr &expr);
|
||||
|
||||
private:
|
||||
CompileBlock (Context *ctx, Bvariable *result);
|
||||
|
||||
tree translated;
|
||||
Bvariable *result;
|
||||
};
|
||||
|
||||
class CompileConditionalBlocks : public HIRCompileBase,
|
||||
public HIR::HIRExpressionVisitor
|
||||
{
|
||||
public:
|
||||
static tree compile (HIR::IfExpr *expr, Context *ctx, Bvariable *result)
|
||||
{
|
||||
CompileConditionalBlocks resolver (ctx, result);
|
||||
expr->accept_vis (resolver);
|
||||
return resolver.translated;
|
||||
}
|
||||
|
||||
void visit (HIR::IfExpr &expr) override;
|
||||
void visit (HIR::IfExprConseqElse &expr) override;
|
||||
void visit (HIR::IfExprConseqIf &expr) override;
|
||||
|
||||
// Empty visit for unused Expression HIR nodes.
|
||||
void visit (HIR::PathInExpression &) override {}
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::ClosureExprInner &) override {}
|
||||
void visit (HIR::ClosureExprInnerTyped &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifier &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifierValue &) override {}
|
||||
void visit (HIR::StructExprFieldIndexValue &) override {}
|
||||
void visit (HIR::StructExprStruct &) override {}
|
||||
void visit (HIR::StructExprStructFields &) override {}
|
||||
void visit (HIR::LiteralExpr &) override {}
|
||||
void visit (HIR::BorrowExpr &) override {}
|
||||
void visit (HIR::DereferenceExpr &) override {}
|
||||
void visit (HIR::ErrorPropagationExpr &) override {}
|
||||
void visit (HIR::NegationExpr &) override {}
|
||||
void visit (HIR::ArithmeticOrLogicalExpr &) override {}
|
||||
void visit (HIR::ComparisonExpr &) override {}
|
||||
void visit (HIR::LazyBooleanExpr &) override {}
|
||||
void visit (HIR::TypeCastExpr &) override {}
|
||||
void visit (HIR::AssignmentExpr &) override {}
|
||||
void visit (HIR::CompoundAssignmentExpr &) override {}
|
||||
void visit (HIR::GroupedExpr &) override {}
|
||||
void visit (HIR::ArrayExpr &) override {}
|
||||
void visit (HIR::ArrayIndexExpr &) override {}
|
||||
void visit (HIR::TupleExpr &) override {}
|
||||
void visit (HIR::TupleIndexExpr &) override {}
|
||||
void visit (HIR::CallExpr &) override {}
|
||||
void visit (HIR::MethodCallExpr &) override {}
|
||||
void visit (HIR::FieldAccessExpr &) override {}
|
||||
void visit (HIR::BlockExpr &) override {}
|
||||
void visit (HIR::ContinueExpr &) override {}
|
||||
void visit (HIR::BreakExpr &) 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::RangeToInclExpr &) override {}
|
||||
void visit (HIR::ReturnExpr &) override {}
|
||||
void visit (HIR::UnsafeBlockExpr &) override {}
|
||||
void visit (HIR::LoopExpr &) override {}
|
||||
void visit (HIR::WhileLoopExpr &) override {}
|
||||
void visit (HIR::WhileLetLoopExpr &) override {}
|
||||
void visit (HIR::ForLoopExpr &) override {}
|
||||
void visit (HIR::IfExprConseqIfLet &) override {}
|
||||
void visit (HIR::IfLetExpr &) override {}
|
||||
void visit (HIR::IfLetExprConseqElse &) override {}
|
||||
void visit (HIR::IfLetExprConseqIf &) override {}
|
||||
void visit (HIR::IfLetExprConseqIfLet &) override {}
|
||||
void visit (HIR::MatchExpr &) override {}
|
||||
void visit (HIR::AwaitExpr &) override {}
|
||||
void visit (HIR::AsyncBlockExpr &) override {}
|
||||
|
||||
private:
|
||||
CompileConditionalBlocks (Context *ctx, Bvariable *result)
|
||||
: HIRCompileBase (ctx), translated (nullptr), result (result)
|
||||
{}
|
||||
|
||||
tree translated;
|
||||
Bvariable *result;
|
||||
};
|
||||
|
||||
class CompileExprWithBlock : public HIRCompileBase,
|
||||
public HIR::HIRExpressionVisitor
|
||||
{
|
||||
public:
|
||||
static tree compile (HIR::ExprWithBlock *expr, Context *ctx,
|
||||
Bvariable *result)
|
||||
{
|
||||
CompileExprWithBlock resolver (ctx, result);
|
||||
expr->accept_vis (resolver);
|
||||
return resolver.translated;
|
||||
}
|
||||
|
||||
void visit (HIR::IfExpr &expr) override
|
||||
{
|
||||
translated = CompileConditionalBlocks::compile (&expr, ctx, result);
|
||||
}
|
||||
|
||||
void visit (HIR::IfExprConseqElse &expr) override
|
||||
{
|
||||
translated = CompileConditionalBlocks::compile (&expr, ctx, result);
|
||||
}
|
||||
|
||||
void visit (HIR::IfExprConseqIf &expr) override
|
||||
{
|
||||
translated = CompileConditionalBlocks::compile (&expr, ctx, result);
|
||||
}
|
||||
|
||||
// Empty visit for unused Expression HIR nodes.
|
||||
void visit (HIR::PathInExpression &) override {}
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::ClosureExprInner &) override {}
|
||||
void visit (HIR::ClosureExprInnerTyped &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifier &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifierValue &) override {}
|
||||
void visit (HIR::StructExprFieldIndexValue &) override {}
|
||||
void visit (HIR::StructExprStruct &) override {}
|
||||
void visit (HIR::StructExprStructFields &) override {}
|
||||
void visit (HIR::LiteralExpr &) override {}
|
||||
void visit (HIR::BorrowExpr &) override {}
|
||||
void visit (HIR::DereferenceExpr &) override {}
|
||||
void visit (HIR::ErrorPropagationExpr &) override {}
|
||||
void visit (HIR::NegationExpr &) override {}
|
||||
void visit (HIR::ArithmeticOrLogicalExpr &) override {}
|
||||
void visit (HIR::ComparisonExpr &) override {}
|
||||
void visit (HIR::LazyBooleanExpr &) override {}
|
||||
void visit (HIR::TypeCastExpr &) override {}
|
||||
void visit (HIR::AssignmentExpr &) override {}
|
||||
void visit (HIR::CompoundAssignmentExpr &) override {}
|
||||
void visit (HIR::GroupedExpr &) override {}
|
||||
void visit (HIR::ArrayExpr &) override {}
|
||||
void visit (HIR::ArrayIndexExpr &) override {}
|
||||
void visit (HIR::TupleExpr &) override {}
|
||||
void visit (HIR::TupleIndexExpr &) override {}
|
||||
void visit (HIR::CallExpr &) override {}
|
||||
void visit (HIR::MethodCallExpr &) override {}
|
||||
void visit (HIR::FieldAccessExpr &) override {}
|
||||
void visit (HIR::BlockExpr &) override {}
|
||||
void visit (HIR::ContinueExpr &) override {}
|
||||
void visit (HIR::BreakExpr &) 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::RangeToInclExpr &) override {}
|
||||
void visit (HIR::ReturnExpr &) override {}
|
||||
void visit (HIR::UnsafeBlockExpr &) override {}
|
||||
void visit (HIR::LoopExpr &) override {}
|
||||
void visit (HIR::WhileLoopExpr &) override {}
|
||||
void visit (HIR::WhileLetLoopExpr &) override {}
|
||||
void visit (HIR::ForLoopExpr &) override {}
|
||||
void visit (HIR::IfExprConseqIfLet &) override {}
|
||||
void visit (HIR::IfLetExpr &) override {}
|
||||
void visit (HIR::IfLetExprConseqElse &) override {}
|
||||
void visit (HIR::IfLetExprConseqIf &) override {}
|
||||
void visit (HIR::IfLetExprConseqIfLet &) override {}
|
||||
void visit (HIR::MatchExpr &) override {}
|
||||
void visit (HIR::AwaitExpr &) override {}
|
||||
void visit (HIR::AsyncBlockExpr &) override {}
|
||||
|
||||
private:
|
||||
CompileExprWithBlock (Context *ctx, Bvariable *result)
|
||||
: HIRCompileBase (ctx), translated (nullptr), result (result)
|
||||
{}
|
||||
|
||||
tree translated;
|
||||
Bvariable *result;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_BLOCK
|
||||
2769
gcc/rust/backend/rust-compile-expr.cc
Normal file
2769
gcc/rust/backend/rust-compile-expr.cc
Normal file
File diff suppressed because it is too large
Load Diff
148
gcc/rust/backend/rust-compile-expr.h
Normal file
148
gcc/rust/backend/rust-compile-expr.h
Normal file
@@ -0,0 +1,148 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_EXPR
|
||||
#define RUST_COMPILE_EXPR
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileExpr : private HIRCompileBase, protected HIR::HIRExpressionVisitor
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::Expr *expr, Context *ctx);
|
||||
|
||||
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::IfExprConseqIf &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;
|
||||
|
||||
// Empty visit for unused Expression HIR nodes.
|
||||
void visit (HIR::ClosureExprInner &) override {}
|
||||
void visit (HIR::ClosureExprInnerTyped &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifier &) override {}
|
||||
void visit (HIR::StructExprFieldIdentifierValue &) override {}
|
||||
void visit (HIR::StructExprFieldIndexValue &) override {}
|
||||
void visit (HIR::ErrorPropagationExpr &) override {}
|
||||
void visit (HIR::RangeToInclExpr &) override {}
|
||||
void visit (HIR::WhileLetLoopExpr &) override {}
|
||||
void visit (HIR::ForLoopExpr &) override {}
|
||||
void visit (HIR::IfExprConseqIfLet &) override {}
|
||||
void visit (HIR::IfLetExpr &) override {}
|
||||
void visit (HIR::IfLetExprConseqElse &) override {}
|
||||
void visit (HIR::IfLetExprConseqIf &) override {}
|
||||
void visit (HIR::IfLetExprConseqIfLet &) override {}
|
||||
void visit (HIR::AwaitExpr &) override {}
|
||||
void visit (HIR::AsyncBlockExpr &) override {}
|
||||
|
||||
protected:
|
||||
tree get_fn_addr_from_dyn (const TyTy::DynamicObjectType *dyn,
|
||||
TyTy::BaseType *receiver, TyTy::FnType *fntype,
|
||||
tree receiver_ref, Location expr_locus);
|
||||
|
||||
tree get_receiver_from_dyn (const TyTy::DynamicObjectType *dyn,
|
||||
TyTy::BaseType *receiver, TyTy::FnType *fntype,
|
||||
tree receiver_ref, Location expr_locus);
|
||||
|
||||
tree resolve_method_address (TyTy::FnType *fntype, HirId ref,
|
||||
TyTy::BaseType *receiver,
|
||||
HIR::PathIdentSegment &segment,
|
||||
Analysis::NodeMapping expr_mappings,
|
||||
Location expr_locus);
|
||||
|
||||
tree
|
||||
resolve_operator_overload (Analysis::RustLangItem::ItemType lang_item_type,
|
||||
HIR::OperatorExprMeta expr, tree lhs, tree rhs,
|
||||
HIR::Expr *lhs_expr, HIR::Expr *rhs_expr);
|
||||
|
||||
tree compile_bool_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_integer_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_float_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_char_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_byte_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_string_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree compile_byte_string_literal (const HIR::LiteralExpr &expr,
|
||||
const TyTy::BaseType *tyty);
|
||||
|
||||
tree type_cast_expression (tree type_to_cast_to, tree expr, Location locus);
|
||||
|
||||
tree array_value_expr (Location expr_locus, const TyTy::ArrayType &array_tyty,
|
||||
tree array_type, HIR::ArrayElemsValues &elems);
|
||||
|
||||
tree array_copied_expr (Location expr_locus,
|
||||
const TyTy::ArrayType &array_tyty, tree array_type,
|
||||
HIR::ArrayElemsCopied &elems);
|
||||
|
||||
private:
|
||||
CompileExpr (Context *ctx);
|
||||
|
||||
tree translated;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_EXPR
|
||||
172
gcc/rust/backend/rust-compile-extern.h
Normal file
172
gcc/rust/backend/rust-compile-extern.h
Normal file
@@ -0,0 +1,172 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_EXTERN_ITEM
|
||||
#define RUST_COMPILE_EXTERN_ITEM
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
#include "rust-compile-intrinsic.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileExternItem : public HIRCompileBase,
|
||||
public HIR::HIRExternalItemVisitor
|
||||
{
|
||||
public:
|
||||
static tree compile (HIR::ExternalItem *item, Context *ctx,
|
||||
TyTy::BaseType *concrete = nullptr,
|
||||
bool is_query_mode = false,
|
||||
Location ref_locus = Location ())
|
||||
{
|
||||
CompileExternItem compiler (ctx, concrete, ref_locus);
|
||||
item->accept_vis (compiler);
|
||||
|
||||
if (is_query_mode && compiler.reference == error_mark_node)
|
||||
rust_internal_error_at (ref_locus, "failed to compile extern item: %s",
|
||||
item->as_string ().c_str ());
|
||||
|
||||
return compiler.reference;
|
||||
}
|
||||
|
||||
void visit (HIR::ExternalStaticItem &item) override
|
||||
{
|
||||
// check if its already been compiled
|
||||
Bvariable *lookup = ctx->get_backend ()->error_variable ();
|
||||
if (ctx->lookup_var_decl (item.get_mappings ().get_hirid (), &lookup))
|
||||
{
|
||||
reference = ctx->get_backend ()->var_expression (lookup, ref_locus);
|
||||
return;
|
||||
}
|
||||
|
||||
TyTy::BaseType *resolved_type = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (item.get_mappings ().get_hirid (),
|
||||
&resolved_type);
|
||||
rust_assert (ok);
|
||||
|
||||
std::string name = item.get_item_name ();
|
||||
// FIXME this is assuming C ABI
|
||||
std::string asm_name = name;
|
||||
|
||||
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
|
||||
bool is_external = true;
|
||||
bool is_hidden = false;
|
||||
bool in_unique_section = false;
|
||||
|
||||
Bvariable *static_global
|
||||
= ctx->get_backend ()->global_variable (name, asm_name, type, is_external,
|
||||
is_hidden, in_unique_section,
|
||||
item.get_locus ());
|
||||
ctx->insert_var_decl (item.get_mappings ().get_hirid (), static_global);
|
||||
ctx->push_var (static_global);
|
||||
|
||||
reference = ctx->get_backend ()->var_expression (static_global, ref_locus);
|
||||
}
|
||||
|
||||
void visit (HIR::ExternalFunctionItem &function) override
|
||||
{
|
||||
TyTy::BaseType *fntype_tyty;
|
||||
if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
|
||||
&fntype_tyty))
|
||||
{
|
||||
rust_fatal_error (function.get_locus (),
|
||||
"failed to lookup function type");
|
||||
return;
|
||||
}
|
||||
|
||||
rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
|
||||
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
|
||||
if (fntype->has_subsititions_defined ())
|
||||
{
|
||||
// we cant do anything for this only when it is used and a concrete type
|
||||
// is given
|
||||
if (concrete == nullptr)
|
||||
return;
|
||||
else
|
||||
{
|
||||
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
|
||||
fntype = static_cast<TyTy::FnType *> (concrete);
|
||||
}
|
||||
}
|
||||
|
||||
// items can be forward compiled which means we may not need to invoke this
|
||||
// code. We might also have already compiled this generic function as well.
|
||||
tree lookup = NULL_TREE;
|
||||
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
|
||||
fntype->get_id (), fntype))
|
||||
{
|
||||
reference = address_expression (lookup, ref_locus);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fntype->has_subsititions_defined ())
|
||||
{
|
||||
// override the Hir Lookups for the substituions in this context
|
||||
fntype->override_context ();
|
||||
}
|
||||
|
||||
if (fntype->get_abi () == ABI::INTRINSIC)
|
||||
{
|
||||
Intrinsics compile (ctx);
|
||||
tree fndecl = compile.compile (fntype);
|
||||
ctx->insert_function_decl (fntype, fndecl);
|
||||
return;
|
||||
}
|
||||
|
||||
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
|
||||
std::string ir_symbol_name = function.get_item_name ();
|
||||
std::string asm_name = function.get_item_name ();
|
||||
if (fntype->get_abi () == ABI::RUST)
|
||||
{
|
||||
// then we need to get the canonical path of it and mangle it
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
bool ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
function.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
ir_symbol_name = canonical_path->get () + fntype->subst_as_string ();
|
||||
asm_name = ctx->mangle_item (fntype, *canonical_path);
|
||||
}
|
||||
|
||||
const unsigned int flags = Backend::function_is_declaration;
|
||||
tree fndecl
|
||||
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name,
|
||||
asm_name, flags, function.get_locus ());
|
||||
TREE_PUBLIC (fndecl) = 1;
|
||||
setup_abi_options (fndecl, fntype->get_abi ());
|
||||
|
||||
ctx->insert_function_decl (fntype, fndecl);
|
||||
|
||||
reference = address_expression (fndecl, ref_locus);
|
||||
}
|
||||
|
||||
private:
|
||||
CompileExternItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
|
||||
: HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
|
||||
ref_locus (ref_locus)
|
||||
{}
|
||||
|
||||
TyTy::BaseType *concrete;
|
||||
tree reference;
|
||||
Location ref_locus;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_EXTERN_ITEM
|
||||
121
gcc/rust/backend/rust-compile-fnparam.cc
Normal file
121
gcc/rust/backend/rust-compile-fnparam.cc
Normal file
@@ -0,0 +1,121 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-fnparam.h"
|
||||
#include "rust-compile-pattern.h"
|
||||
|
||||
#include "gimple-expr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
CompileFnParam::CompileFnParam (Context *ctx, tree fndecl, tree decl_type,
|
||||
Location locus)
|
||||
: HIRCompileBase (ctx), fndecl (fndecl), decl_type (decl_type), locus (locus),
|
||||
compiled_param (ctx->get_backend ()->error_variable ())
|
||||
{}
|
||||
|
||||
Bvariable *
|
||||
CompileFnParam::compile (Context *ctx, tree fndecl, HIR::FunctionParam *param,
|
||||
tree decl_type, Location locus)
|
||||
{
|
||||
CompileFnParam compiler (ctx, fndecl, decl_type, locus);
|
||||
param->get_param_name ()->accept_vis (compiler);
|
||||
return compiler.compiled_param;
|
||||
}
|
||||
|
||||
Bvariable *
|
||||
CompileFnParam::compile (Context *ctx, tree fndecl, HIR::Pattern *param,
|
||||
tree decl_type, Location locus)
|
||||
{
|
||||
CompileFnParam compiler (ctx, fndecl, decl_type, locus);
|
||||
param->accept_vis (compiler);
|
||||
return compiler.compiled_param;
|
||||
}
|
||||
|
||||
void
|
||||
CompileFnParam::visit (HIR::IdentifierPattern &pattern)
|
||||
{
|
||||
if (!pattern.is_mut ())
|
||||
decl_type = ctx->get_backend ()->immutable_type (decl_type);
|
||||
|
||||
compiled_param
|
||||
= ctx->get_backend ()->parameter_variable (fndecl,
|
||||
pattern.get_identifier (),
|
||||
decl_type, locus);
|
||||
}
|
||||
|
||||
void
|
||||
CompileFnParam::visit (HIR::WildcardPattern &pattern)
|
||||
{
|
||||
decl_type = ctx->get_backend ()->immutable_type (decl_type);
|
||||
|
||||
compiled_param
|
||||
= ctx->get_backend ()->parameter_variable (fndecl, "_", decl_type, locus);
|
||||
}
|
||||
|
||||
void
|
||||
CompileFnParam::visit (HIR::StructPattern &pattern)
|
||||
{
|
||||
// generate the anon param
|
||||
tree tmp_ident = create_tmp_var_name ("RSTPRM");
|
||||
std::string cpp_str_identifier = std::string (IDENTIFIER_POINTER (tmp_ident));
|
||||
|
||||
decl_type = ctx->get_backend ()->immutable_type (decl_type);
|
||||
compiled_param
|
||||
= ctx->get_backend ()->parameter_variable (fndecl, cpp_str_identifier,
|
||||
decl_type, locus);
|
||||
|
||||
// setup the pattern bindings
|
||||
tree anon_param = ctx->get_backend ()->var_expression (compiled_param, locus);
|
||||
CompilePatternBindings::Compile (&pattern, anon_param, ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileFnParam::visit (HIR::TupleStructPattern &pattern)
|
||||
{
|
||||
// generate the anon param
|
||||
tree tmp_ident = create_tmp_var_name ("RSTPRM");
|
||||
std::string cpp_str_identifier = std::string (IDENTIFIER_POINTER (tmp_ident));
|
||||
|
||||
decl_type = ctx->get_backend ()->immutable_type (decl_type);
|
||||
compiled_param
|
||||
= ctx->get_backend ()->parameter_variable (fndecl, cpp_str_identifier,
|
||||
decl_type, locus);
|
||||
|
||||
// setup the pattern bindings
|
||||
tree anon_param = ctx->get_backend ()->var_expression (compiled_param, locus);
|
||||
CompilePatternBindings::Compile (&pattern, anon_param, ctx);
|
||||
}
|
||||
|
||||
Bvariable *
|
||||
CompileSelfParam::compile (Context *ctx, tree fndecl, HIR::SelfParam &self,
|
||||
tree decl_type, Location locus)
|
||||
{
|
||||
bool is_immutable
|
||||
= self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM
|
||||
|| self.get_self_kind () == HIR::SelfParam::ImplicitSelfKind::IMM_REF;
|
||||
if (is_immutable)
|
||||
decl_type = ctx->get_backend ()->immutable_type (decl_type);
|
||||
|
||||
return ctx->get_backend ()->parameter_variable (fndecl, "self", decl_type,
|
||||
locus);
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
70
gcc/rust/backend/rust-compile-fnparam.h
Normal file
70
gcc/rust/backend/rust-compile-fnparam.h
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_FNPARAM
|
||||
#define RUST_COMPILE_FNPARAM
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileFnParam : private HIRCompileBase, protected HIR::HIRPatternVisitor
|
||||
{
|
||||
public:
|
||||
static Bvariable *compile (Context *ctx, tree fndecl,
|
||||
HIR::FunctionParam *param, tree decl_type,
|
||||
Location locus);
|
||||
static Bvariable *compile (Context *ctx, tree fndecl, HIR::Pattern *param,
|
||||
tree decl_type, Location locus);
|
||||
|
||||
void visit (HIR::IdentifierPattern &pattern) override;
|
||||
void visit (HIR::WildcardPattern &pattern) override;
|
||||
void visit (HIR::StructPattern &) override;
|
||||
void visit (HIR::TupleStructPattern &) override;
|
||||
|
||||
// Empty visit for unused Pattern HIR nodes.
|
||||
void visit (HIR::GroupedPattern &) override {}
|
||||
void visit (HIR::LiteralPattern &) override {}
|
||||
void visit (HIR::PathInExpression &) override {}
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::RangePattern &) override {}
|
||||
void visit (HIR::ReferencePattern &) override {}
|
||||
void visit (HIR::SlicePattern &) override {}
|
||||
void visit (HIR::TuplePattern &) override {}
|
||||
|
||||
private:
|
||||
CompileFnParam (Context *ctx, tree fndecl, tree decl_type, Location locus);
|
||||
|
||||
tree fndecl;
|
||||
tree decl_type;
|
||||
Location locus;
|
||||
Bvariable *compiled_param;
|
||||
};
|
||||
|
||||
class CompileSelfParam : private HIRCompileBase
|
||||
{
|
||||
public:
|
||||
static Bvariable *compile (Context *ctx, tree fndecl, HIR::SelfParam &self,
|
||||
tree decl_type, Location locus);
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_FNPARAM
|
||||
101
gcc/rust/backend/rust-compile-implitem.cc
Normal file
101
gcc/rust/backend/rust-compile-implitem.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-implitem.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-compile-fnparam.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
void
|
||||
CompileTraitItem::visit (HIR::TraitItemConst &constant)
|
||||
{
|
||||
rust_assert (concrete != nullptr);
|
||||
TyTy::BaseType *resolved_type = concrete;
|
||||
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
bool ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
constant.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
HIR::Expr *const_value_expr = constant.get_expr ().get ();
|
||||
tree const_expr
|
||||
= compile_constant_item (ctx, resolved_type, canonical_path,
|
||||
const_value_expr, constant.get_locus ());
|
||||
ctx->push_const (const_expr);
|
||||
ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr);
|
||||
|
||||
reference = const_expr;
|
||||
}
|
||||
|
||||
void
|
||||
CompileTraitItem::visit (HIR::TraitItemFunc &func)
|
||||
{
|
||||
rust_assert (func.has_block_defined ());
|
||||
|
||||
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
|
||||
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (concrete);
|
||||
fntype->monomorphize ();
|
||||
|
||||
// items can be forward compiled which means we may not need to invoke this
|
||||
// code. We might also have already compiled this generic function as well.
|
||||
tree lookup = NULL_TREE;
|
||||
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
|
||||
fntype->get_id (), fntype))
|
||||
{
|
||||
// has this been added to the list then it must be finished
|
||||
if (ctx->function_completed (lookup))
|
||||
{
|
||||
tree dummy = NULL_TREE;
|
||||
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
|
||||
{
|
||||
ctx->insert_function_decl (fntype, lookup);
|
||||
}
|
||||
|
||||
reference = address_expression (lookup, ref_locus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fntype->has_subsititions_defined ())
|
||||
{
|
||||
// override the Hir Lookups for the substituions in this context
|
||||
fntype->override_context ();
|
||||
}
|
||||
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
bool ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
func.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
// FIXME: How do we get the proper visibility here?
|
||||
auto vis = HIR::Visibility (HIR::Visibility::VisType::PUBLIC);
|
||||
HIR::TraitFunctionDecl &function = func.get_decl ();
|
||||
tree fndecl
|
||||
= compile_function (ctx, function.get_function_name (),
|
||||
function.get_self (), function.get_function_params (),
|
||||
function.get_qualifiers (), vis,
|
||||
func.get_outer_attrs (), func.get_locus (),
|
||||
func.get_block_expr ().get (), canonical_path, fntype,
|
||||
function.has_return_type ());
|
||||
reference = address_expression (fndecl, ref_locus);
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
91
gcc/rust/backend/rust-compile-implitem.h
Normal file
91
gcc/rust/backend/rust-compile-implitem.h
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_IMPLITEM_H
|
||||
#define RUST_COMPILE_IMPLITEM_H
|
||||
|
||||
#include "rust-compile-item.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-compile-fnparam.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
// this is a proxy for HIR::ImplItem's back to use the normel HIR::Item path
|
||||
class CompileInherentImplItem : public CompileItem
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::ImplItem *item, Context *ctx,
|
||||
TyTy::BaseType *concrete = nullptr,
|
||||
bool is_query_mode = false,
|
||||
Location ref_locus = Location ())
|
||||
{
|
||||
CompileInherentImplItem compiler (ctx, concrete, ref_locus);
|
||||
item->accept_vis (compiler);
|
||||
|
||||
if (is_query_mode && compiler.reference == error_mark_node)
|
||||
rust_internal_error_at (ref_locus, "failed to compile impl item: %s",
|
||||
item->as_string ().c_str ());
|
||||
|
||||
return compiler.reference;
|
||||
}
|
||||
|
||||
private:
|
||||
CompileInherentImplItem (Context *ctx, TyTy::BaseType *concrete,
|
||||
Location ref_locus)
|
||||
: CompileItem (ctx, concrete, ref_locus)
|
||||
{}
|
||||
};
|
||||
|
||||
class CompileTraitItem : public HIRCompileBase, public HIR::HIRTraitItemVisitor
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::TraitItem *item, Context *ctx,
|
||||
TyTy::BaseType *concrete, bool is_query_mode = false,
|
||||
Location ref_locus = Location ())
|
||||
{
|
||||
CompileTraitItem compiler (ctx, concrete, ref_locus);
|
||||
item->accept_vis (compiler);
|
||||
|
||||
if (is_query_mode && compiler.reference == error_mark_node)
|
||||
rust_internal_error_at (ref_locus, "failed to compile trait item: %s",
|
||||
item->as_string ().c_str ());
|
||||
|
||||
return compiler.reference;
|
||||
}
|
||||
|
||||
void visit (HIR::TraitItemConst &constant) override;
|
||||
void visit (HIR::TraitItemFunc &func) override;
|
||||
|
||||
void visit (HIR::TraitItemType &typ) override {}
|
||||
|
||||
private:
|
||||
CompileTraitItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
|
||||
: HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
|
||||
ref_locus (ref_locus)
|
||||
{}
|
||||
|
||||
TyTy::BaseType *concrete;
|
||||
tree reference;
|
||||
Location ref_locus;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_IMPLITEM_H
|
||||
515
gcc/rust/backend/rust-compile-intrinsic.cc
Normal file
515
gcc/rust/backend/rust-compile-intrinsic.cc
Normal file
@@ -0,0 +1,515 @@
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-intrinsic.h"
|
||||
#include "fold-const.h"
|
||||
#include "langhooks.h"
|
||||
#include "rust-compile-context.h"
|
||||
#include "rust-compile-type.h"
|
||||
#include "rust-compile-fnparam.h"
|
||||
#include "rust-builtins.h"
|
||||
#include "rust-diagnostics.h"
|
||||
#include "rust-location.h"
|
||||
#include "rust-tree.h"
|
||||
#include "tree-core.h"
|
||||
#include "print-tree.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
static tree
|
||||
offset_handler (Context *ctx, TyTy::FnType *fntype);
|
||||
static tree
|
||||
sizeof_handler (Context *ctx, TyTy::FnType *fntype);
|
||||
static tree
|
||||
transmute_handler (Context *ctx, TyTy::FnType *fntype);
|
||||
static tree
|
||||
rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
|
||||
static tree
|
||||
wrapping_op_handler (Context *ctx, TyTy::FnType *fntype, tree_code op);
|
||||
static tree
|
||||
copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype);
|
||||
|
||||
static inline tree
|
||||
rotate_left_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
return rotate_handler (ctx, fntype, LROTATE_EXPR);
|
||||
}
|
||||
static inline tree
|
||||
rotate_right_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
return rotate_handler (ctx, fntype, RROTATE_EXPR);
|
||||
}
|
||||
|
||||
static inline tree
|
||||
wrapping_add_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
return wrapping_op_handler (ctx, fntype, PLUS_EXPR);
|
||||
}
|
||||
static inline tree
|
||||
wrapping_sub_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
return wrapping_op_handler (ctx, fntype, MINUS_EXPR);
|
||||
}
|
||||
static inline tree
|
||||
wrapping_mul_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
return wrapping_op_handler (ctx, fntype, MULT_EXPR);
|
||||
}
|
||||
|
||||
static const std::map<std::string,
|
||||
std::function<tree (Context *, TyTy::FnType *)>>
|
||||
generic_intrinsics = {{"offset", &offset_handler},
|
||||
{"size_of", &sizeof_handler},
|
||||
{"transmute", &transmute_handler},
|
||||
{"rotate_left", &rotate_left_handler},
|
||||
{"rotate_right", &rotate_right_handler},
|
||||
{"wrapping_add", &wrapping_add_handler},
|
||||
{"wrapping_sub", &wrapping_sub_handler},
|
||||
{"wrapping_mul", &wrapping_mul_handler},
|
||||
{"copy_nonoverlapping", ©_nonoverlapping_handler}};
|
||||
|
||||
Intrinsics::Intrinsics (Context *ctx) : ctx (ctx) {}
|
||||
|
||||
tree
|
||||
Intrinsics::compile (TyTy::FnType *fntype)
|
||||
{
|
||||
rust_assert (fntype->get_abi () == ABI::INTRINSIC);
|
||||
|
||||
tree builtin = error_mark_node;
|
||||
BuiltinsContext &builtin_ctx = BuiltinsContext::get ();
|
||||
if (builtin_ctx.lookup_simple_builtin (fntype->get_identifier (), &builtin))
|
||||
return builtin;
|
||||
|
||||
// is it an generic builtin?
|
||||
auto it = generic_intrinsics.find (fntype->get_identifier ());
|
||||
if (it != generic_intrinsics.end ())
|
||||
return it->second (ctx, fntype);
|
||||
|
||||
Location locus = ctx->get_mappings ()->lookup_location (fntype->get_ref ());
|
||||
rust_error_at (locus, "unknown builtin intrinsic: %s",
|
||||
fntype->get_identifier ().c_str ());
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Items can be forward compiled which means we may not need to invoke this
|
||||
* code. We might also have already compiled this generic function as well.
|
||||
*/
|
||||
static bool
|
||||
check_for_cached_intrinsic (Context *ctx, TyTy::FnType *fntype, tree *lookup)
|
||||
{
|
||||
if (ctx->lookup_function_decl (fntype->get_ty_ref (), lookup,
|
||||
fntype->get_id (), fntype))
|
||||
{
|
||||
// Has this been added to the list? Then it must be finished
|
||||
if (ctx->function_completed (*lookup))
|
||||
{
|
||||
tree dummy = NULL_TREE;
|
||||
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
|
||||
ctx->insert_function_decl (fntype, *lookup);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maybe override the Hir Lookups for the substituions in this context
|
||||
*/
|
||||
static void
|
||||
maybe_override_ctx (TyTy::FnType *fntype)
|
||||
{
|
||||
if (fntype->has_subsititions_defined ())
|
||||
fntype->override_context ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compile and setup a function's parameters
|
||||
*/
|
||||
static void
|
||||
compile_fn_params (Context *ctx, TyTy::FnType *fntype, tree fndecl,
|
||||
std::vector<Bvariable *> *compiled_param_variables,
|
||||
std::vector<tree_node *> *compiled_param_types = nullptr)
|
||||
{
|
||||
for (auto &parm : fntype->get_params ())
|
||||
{
|
||||
auto &referenced_param = parm.first;
|
||||
auto ¶m_tyty = parm.second;
|
||||
auto compiled_param_type = TyTyResolveCompile::compile (ctx, param_tyty);
|
||||
|
||||
Location param_locus = referenced_param->get_locus ();
|
||||
Bvariable *compiled_param_var
|
||||
= CompileFnParam::compile (ctx, fndecl, referenced_param,
|
||||
compiled_param_type, param_locus);
|
||||
|
||||
compiled_param_variables->push_back (compiled_param_var);
|
||||
if (compiled_param_types)
|
||||
compiled_param_types->push_back (compiled_param_type);
|
||||
}
|
||||
}
|
||||
|
||||
static tree
|
||||
compile_intrinsic_function (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
maybe_override_ctx (fntype);
|
||||
|
||||
const Resolver::CanonicalPath &canonical_path = fntype->get_ident ().path;
|
||||
|
||||
tree compiled_fn_type = TyTyResolveCompile::compile (ctx, fntype);
|
||||
std::string ir_symbol_name
|
||||
= canonical_path.get () + fntype->subst_as_string ();
|
||||
std::string asm_name = ctx->mangle_item (fntype, canonical_path);
|
||||
|
||||
unsigned int flags = 0;
|
||||
tree fndecl
|
||||
= ctx->get_backend ()->function (compiled_fn_type, ir_symbol_name, asm_name,
|
||||
flags, fntype->get_ident ().locus);
|
||||
|
||||
TREE_PUBLIC (fndecl) = 0;
|
||||
TREE_READONLY (fndecl) = 1;
|
||||
DECL_ARTIFICIAL (fndecl) = 1;
|
||||
DECL_EXTERNAL (fndecl) = 0;
|
||||
DECL_DECLARED_INLINE_P (fndecl) = 1;
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
static void
|
||||
enter_intrinsic_block (Context *ctx, tree fndecl)
|
||||
{
|
||||
tree enclosing_scope = NULL_TREE;
|
||||
Location start_location = Location ();
|
||||
Location end_location = Location ();
|
||||
|
||||
auto block = ctx->get_backend ()->block (fndecl, enclosing_scope, {},
|
||||
start_location, end_location);
|
||||
|
||||
ctx->push_block (block);
|
||||
}
|
||||
|
||||
static void
|
||||
finalize_intrinsic_block (Context *ctx, tree fndecl)
|
||||
{
|
||||
tree bind_tree = ctx->pop_block ();
|
||||
|
||||
gcc_assert (TREE_CODE (bind_tree) == BIND_EXPR);
|
||||
|
||||
DECL_SAVED_TREE (fndecl) = bind_tree;
|
||||
|
||||
ctx->push_function (fndecl);
|
||||
}
|
||||
|
||||
static tree
|
||||
offset_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
// offset intrinsic has two params dst pointer and offset isize
|
||||
rust_assert (fntype->get_params ().size () == 2);
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
std::vector<Bvariable *> param_vars;
|
||||
compile_fn_params (ctx, fntype, fndecl, ¶m_vars);
|
||||
|
||||
auto &dst_param = param_vars.at (0);
|
||||
auto &size_param = param_vars.at (1);
|
||||
rust_assert (param_vars.size () == 2);
|
||||
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
|
||||
return error_mark_node;
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN offset FN BODY BEGIN
|
||||
tree dst = ctx->get_backend ()->var_expression (dst_param, Location ());
|
||||
tree size = ctx->get_backend ()->var_expression (size_param, Location ());
|
||||
tree pointer_offset_expr
|
||||
= pointer_offset_expression (dst, size, BUILTINS_LOCATION);
|
||||
auto return_statement
|
||||
= ctx->get_backend ()->return_statement (fndecl, {pointer_offset_expr},
|
||||
Location ());
|
||||
ctx->add_statement (return_statement);
|
||||
// BUILTIN offset FN BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
static tree
|
||||
sizeof_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
// size_of has _zero_ parameters its parameter is the generic one
|
||||
rust_assert (fntype->get_params ().size () == 0);
|
||||
|
||||
tree lookup = NULL_TREE;
|
||||
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
|
||||
return lookup;
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
// get the template parameter type tree fn size_of<T>();
|
||||
rust_assert (fntype->get_num_substitutions () == 1);
|
||||
auto ¶m_mapping = fntype->get_substs ().at (0);
|
||||
const TyTy::ParamType *param_tyty = param_mapping.get_param_ty ();
|
||||
TyTy::BaseType *resolved_tyty = param_tyty->resolve ();
|
||||
tree template_parameter_type
|
||||
= TyTyResolveCompile::compile (ctx, resolved_tyty);
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN size_of FN BODY BEGIN
|
||||
tree size_expr = TYPE_SIZE_UNIT (template_parameter_type);
|
||||
auto return_statement
|
||||
= ctx->get_backend ()->return_statement (fndecl, {size_expr}, Location ());
|
||||
ctx->add_statement (return_statement);
|
||||
// BUILTIN size_of FN BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
static tree
|
||||
transmute_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
// transmute intrinsic has one parameter
|
||||
rust_assert (fntype->get_params ().size () == 1);
|
||||
|
||||
tree lookup = NULL_TREE;
|
||||
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
|
||||
return lookup;
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
std::vector<Bvariable *> param_vars;
|
||||
std::vector<tree_node *> compiled_types;
|
||||
compile_fn_params (ctx, fntype, fndecl, ¶m_vars, &compiled_types);
|
||||
|
||||
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
|
||||
return error_mark_node;
|
||||
|
||||
// param to convert
|
||||
Bvariable *convert_me_param = param_vars.at (0);
|
||||
tree convert_me_expr
|
||||
= ctx->get_backend ()->var_expression (convert_me_param, Location ());
|
||||
|
||||
// check for transmute pre-conditions
|
||||
tree target_type_expr = TREE_TYPE (DECL_RESULT (fndecl));
|
||||
tree source_type_expr = compiled_types.at (0);
|
||||
tree target_size_expr = TYPE_SIZE (target_type_expr);
|
||||
tree source_size_expr = TYPE_SIZE (source_type_expr);
|
||||
// for some reason, unit types and other zero-sized types return NULL for the
|
||||
// size expressions
|
||||
unsigned HOST_WIDE_INT target_size
|
||||
= target_size_expr ? TREE_INT_CST_LOW (target_size_expr) : 0;
|
||||
unsigned HOST_WIDE_INT source_size
|
||||
= source_size_expr ? TREE_INT_CST_LOW (source_size_expr) : 0;
|
||||
|
||||
// size check for concrete types
|
||||
// TODO(liushuyu): check alignment for pointers; check for dependently-sized
|
||||
// types
|
||||
if (target_size != source_size)
|
||||
{
|
||||
rust_error_at (fntype->get_locus (),
|
||||
"cannot transmute between types of different sizes, or "
|
||||
"dependently-sized types");
|
||||
rust_inform (fntype->get_ident ().locus, "source type: %qs (%lu bits)",
|
||||
fntype->get_params ().at (0).second->as_string ().c_str (),
|
||||
(unsigned long) source_size);
|
||||
rust_inform (fntype->get_ident ().locus, "target type: %qs (%lu bits)",
|
||||
fntype->get_return_type ()->as_string ().c_str (),
|
||||
(unsigned long) target_size);
|
||||
}
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN transmute FN BODY BEGIN
|
||||
|
||||
// Return *((orig_type*)&decl) */
|
||||
|
||||
tree t
|
||||
= build_fold_addr_expr_loc (Location ().gcc_location (), convert_me_expr);
|
||||
t = fold_build1_loc (Location ().gcc_location (), NOP_EXPR,
|
||||
build_pointer_type (target_type_expr), t);
|
||||
tree result_expr
|
||||
= build_fold_indirect_ref_loc (Location ().gcc_location (), t);
|
||||
|
||||
auto return_statement
|
||||
= ctx->get_backend ()->return_statement (fndecl, {result_expr},
|
||||
Location ());
|
||||
ctx->add_statement (return_statement);
|
||||
// BUILTIN transmute FN BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
static tree
|
||||
rotate_handler (Context *ctx, TyTy::FnType *fntype, tree_code op)
|
||||
{
|
||||
// rotate intrinsic has two parameter
|
||||
rust_assert (fntype->get_params ().size () == 2);
|
||||
|
||||
tree lookup = NULL_TREE;
|
||||
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
|
||||
return lookup;
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
// setup the params
|
||||
std::vector<Bvariable *> param_vars;
|
||||
compile_fn_params (ctx, fntype, fndecl, ¶m_vars);
|
||||
|
||||
auto &x_param = param_vars.at (0);
|
||||
auto &y_param = param_vars.at (1);
|
||||
rust_assert (param_vars.size () == 2);
|
||||
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
|
||||
return error_mark_node;
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN rotate FN BODY BEGIN
|
||||
tree x = ctx->get_backend ()->var_expression (x_param, Location ());
|
||||
tree y = ctx->get_backend ()->var_expression (y_param, Location ());
|
||||
tree rotate_expr
|
||||
= fold_build2_loc (BUILTINS_LOCATION, op, TREE_TYPE (x), x, y);
|
||||
auto return_statement
|
||||
= ctx->get_backend ()->return_statement (fndecl, {rotate_expr},
|
||||
Location ());
|
||||
ctx->add_statement (return_statement);
|
||||
// BUILTIN rotate FN BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
/**
|
||||
* pub fn wrapping_{add, sub, mul}<T>(lhs: T, rhs: T) -> T;
|
||||
*/
|
||||
static tree
|
||||
wrapping_op_handler (Context *ctx, TyTy::FnType *fntype, tree_code op)
|
||||
{
|
||||
// wrapping_<op> intrinsics have two parameter
|
||||
rust_assert (fntype->get_params ().size () == 2);
|
||||
|
||||
tree lookup = NULL_TREE;
|
||||
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
|
||||
return lookup;
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
// setup the params
|
||||
std::vector<Bvariable *> param_vars;
|
||||
compile_fn_params (ctx, fntype, fndecl, ¶m_vars);
|
||||
|
||||
auto &lhs_param = param_vars.at (0);
|
||||
auto &rhs_param = param_vars.at (1);
|
||||
|
||||
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
|
||||
return error_mark_node;
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN wrapping_<op> FN BODY BEGIN
|
||||
auto lhs = ctx->get_backend ()->var_expression (lhs_param, Location ());
|
||||
auto rhs = ctx->get_backend ()->var_expression (rhs_param, Location ());
|
||||
|
||||
// Operations are always wrapping in Rust, as we have -fwrapv enabled by
|
||||
// default. The difference between a wrapping_{add, sub, mul} and a regular
|
||||
// arithmetic operation is that these intrinsics do not panic - they always
|
||||
// carry over.
|
||||
auto wrap_expr = build2 (op, TREE_TYPE (lhs), lhs, rhs);
|
||||
|
||||
auto return_statement
|
||||
= ctx->get_backend ()->return_statement (fndecl, {wrap_expr}, Location ());
|
||||
ctx->add_statement (return_statement);
|
||||
// BUILTIN wrapping_<op> FN BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
/**
|
||||
* fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
|
||||
*/
|
||||
static tree
|
||||
copy_nonoverlapping_handler (Context *ctx, TyTy::FnType *fntype)
|
||||
{
|
||||
rust_assert (fntype->get_params ().size () == 3);
|
||||
rust_assert (fntype->get_num_substitutions () == 1);
|
||||
|
||||
tree lookup = NULL_TREE;
|
||||
if (check_for_cached_intrinsic (ctx, fntype, &lookup))
|
||||
return lookup;
|
||||
|
||||
auto fndecl = compile_intrinsic_function (ctx, fntype);
|
||||
|
||||
// Most intrinsic functions are pure - not `copy_nonoverlapping`
|
||||
TREE_READONLY (fndecl) = 0;
|
||||
TREE_SIDE_EFFECTS (fndecl) = 1;
|
||||
|
||||
// setup the params
|
||||
std::vector<Bvariable *> param_vars;
|
||||
compile_fn_params (ctx, fntype, fndecl, ¶m_vars);
|
||||
|
||||
if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars))
|
||||
return error_mark_node;
|
||||
|
||||
enter_intrinsic_block (ctx, fndecl);
|
||||
|
||||
// BUILTIN copy_nonoverlapping BODY BEGIN
|
||||
|
||||
auto src = ctx->get_backend ()->var_expression (param_vars[0], Location ());
|
||||
auto dst = ctx->get_backend ()->var_expression (param_vars[1], Location ());
|
||||
auto count = ctx->get_backend ()->var_expression (param_vars[2], Location ());
|
||||
|
||||
// We want to create the following statement
|
||||
// memcpy(dst, src, size_of::<T>());
|
||||
// so
|
||||
// memcpy(dst, src, size_expr);
|
||||
|
||||
auto *resolved_ty = fntype->get_substs ().at (0).get_param_ty ()->resolve ();
|
||||
auto param_type = TyTyResolveCompile::compile (ctx, resolved_ty);
|
||||
|
||||
tree size_expr
|
||||
= build2 (MULT_EXPR, size_type_node, TYPE_SIZE_UNIT (param_type), count);
|
||||
|
||||
tree memcpy_raw = nullptr;
|
||||
BuiltinsContext::get ().lookup_simple_builtin ("memcpy", &memcpy_raw);
|
||||
rust_assert (memcpy_raw);
|
||||
auto memcpy
|
||||
= build_fold_addr_expr_loc (Location ().gcc_location (), memcpy_raw);
|
||||
|
||||
auto copy_call
|
||||
= ctx->get_backend ()->call_expression (memcpy, {dst, src, size_expr},
|
||||
nullptr, Location ());
|
||||
|
||||
ctx->add_statement (copy_call);
|
||||
|
||||
// BUILTIN copy_nonoverlapping BODY END
|
||||
|
||||
finalize_intrinsic_block (ctx, fndecl);
|
||||
|
||||
return fndecl;
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
40
gcc/rust/backend/rust-compile-intrinsic.h
Normal file
40
gcc/rust/backend/rust-compile-intrinsic.h
Normal file
@@ -0,0 +1,40 @@
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_INTRINSIC
|
||||
#define RUST_COMPILE_INTRINSIC
|
||||
|
||||
#include "rust-compile-context.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class Intrinsics
|
||||
{
|
||||
public:
|
||||
Intrinsics (Context *ctx);
|
||||
|
||||
tree compile (TyTy::FnType *fntype);
|
||||
|
||||
private:
|
||||
Context *ctx;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_INTRINSIC
|
||||
206
gcc/rust/backend/rust-compile-item.cc
Normal file
206
gcc/rust/backend/rust-compile-item.cc
Normal file
@@ -0,0 +1,206 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-item.h"
|
||||
#include "rust-compile-implitem.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-compile-extern.h"
|
||||
#include "rust-constexpr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::StaticItem &var)
|
||||
{
|
||||
// have we already compiled this?
|
||||
Bvariable *static_decl_ref = nullptr;
|
||||
if (ctx->lookup_var_decl (var.get_mappings ().get_hirid (), &static_decl_ref))
|
||||
{
|
||||
reference
|
||||
= ctx->get_backend ()->var_expression (static_decl_ref, ref_locus);
|
||||
return;
|
||||
}
|
||||
|
||||
TyTy::BaseType *resolved_type = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (var.get_mappings ().get_hirid (),
|
||||
&resolved_type);
|
||||
rust_assert (ok);
|
||||
|
||||
tree type = TyTyResolveCompile::compile (ctx, resolved_type);
|
||||
tree value = CompileExpr::Compile (var.get_expr (), ctx);
|
||||
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
var.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
std::string name = canonical_path->get ();
|
||||
std::string asm_name = ctx->mangle_item (resolved_type, *canonical_path);
|
||||
|
||||
bool is_external = false;
|
||||
bool is_hidden = false;
|
||||
bool in_unique_section = true;
|
||||
|
||||
Bvariable *static_global
|
||||
= ctx->get_backend ()->global_variable (name, asm_name, type, is_external,
|
||||
is_hidden, in_unique_section,
|
||||
var.get_locus ());
|
||||
ctx->get_backend ()->global_variable_set_init (static_global, value);
|
||||
|
||||
ctx->insert_var_decl (var.get_mappings ().get_hirid (), static_global);
|
||||
ctx->push_var (static_global);
|
||||
|
||||
reference = ctx->get_backend ()->var_expression (static_global, ref_locus);
|
||||
}
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::ConstantItem &constant)
|
||||
{
|
||||
if (ctx->lookup_const_decl (constant.get_mappings ().get_hirid (),
|
||||
&reference))
|
||||
return;
|
||||
|
||||
// resolve the type
|
||||
TyTy::BaseType *resolved_type = nullptr;
|
||||
bool ok
|
||||
= ctx->get_tyctx ()->lookup_type (constant.get_mappings ().get_hirid (),
|
||||
&resolved_type);
|
||||
rust_assert (ok);
|
||||
|
||||
// canonical path
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
constant.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
HIR::Expr *const_value_expr = constant.get_expr ();
|
||||
ctx->push_const_context ();
|
||||
tree const_expr
|
||||
= compile_constant_item (ctx, resolved_type, canonical_path,
|
||||
const_value_expr, constant.get_locus ());
|
||||
ctx->pop_const_context ();
|
||||
|
||||
ctx->push_const (const_expr);
|
||||
ctx->insert_const_decl (constant.get_mappings ().get_hirid (), const_expr);
|
||||
reference = const_expr;
|
||||
}
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::Function &function)
|
||||
{
|
||||
TyTy::BaseType *fntype_tyty;
|
||||
if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (),
|
||||
&fntype_tyty))
|
||||
{
|
||||
rust_fatal_error (function.get_locus (),
|
||||
"failed to lookup function type");
|
||||
return;
|
||||
}
|
||||
|
||||
rust_assert (fntype_tyty->get_kind () == TyTy::TypeKind::FNDEF);
|
||||
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (fntype_tyty);
|
||||
if (fntype->has_subsititions_defined ())
|
||||
{
|
||||
// we cant do anything for this only when it is used and a concrete type
|
||||
// is given
|
||||
if (concrete == nullptr)
|
||||
return;
|
||||
else
|
||||
{
|
||||
rust_assert (concrete->get_kind () == TyTy::TypeKind::FNDEF);
|
||||
fntype = static_cast<TyTy::FnType *> (concrete);
|
||||
fntype->monomorphize ();
|
||||
}
|
||||
}
|
||||
|
||||
// items can be forward compiled which means we may not need to invoke this
|
||||
// code. We might also have already compiled this generic function as well.
|
||||
tree lookup = NULL_TREE;
|
||||
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &lookup,
|
||||
fntype->get_id (), fntype))
|
||||
{
|
||||
// has this been added to the list then it must be finished
|
||||
if (ctx->function_completed (lookup))
|
||||
{
|
||||
tree dummy = NULL_TREE;
|
||||
if (!ctx->lookup_function_decl (fntype->get_ty_ref (), &dummy))
|
||||
{
|
||||
ctx->insert_function_decl (fntype, lookup);
|
||||
}
|
||||
|
||||
reference = address_expression (lookup, ref_locus);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (fntype->has_subsititions_defined ())
|
||||
{
|
||||
// override the Hir Lookups for the substituions in this context
|
||||
fntype->override_context ();
|
||||
}
|
||||
|
||||
const Resolver::CanonicalPath *canonical_path = nullptr;
|
||||
bool ok = ctx->get_mappings ()->lookup_canonical_path (
|
||||
function.get_mappings ().get_nodeid (), &canonical_path);
|
||||
rust_assert (ok);
|
||||
|
||||
tree fndecl
|
||||
= compile_function (ctx, function.get_function_name (),
|
||||
function.get_self_param (),
|
||||
function.get_function_params (),
|
||||
function.get_qualifiers (), function.get_visibility (),
|
||||
function.get_outer_attrs (), function.get_locus (),
|
||||
function.get_definition ().get (), canonical_path,
|
||||
fntype, function.has_function_return_type ());
|
||||
reference = address_expression (fndecl, ref_locus);
|
||||
}
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::ImplBlock &impl_block)
|
||||
{
|
||||
TyTy::BaseType *self_lookup = nullptr;
|
||||
if (!ctx->get_tyctx ()->lookup_type (
|
||||
impl_block.get_type ()->get_mappings ().get_hirid (), &self_lookup))
|
||||
{
|
||||
rust_error_at (impl_block.get_locus (), "failed to resolve type of impl");
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto &impl_item : impl_block.get_impl_items ())
|
||||
CompileInherentImplItem::Compile (impl_item.get (), ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::ExternBlock &extern_block)
|
||||
{
|
||||
for (auto &item : extern_block.get_extern_items ())
|
||||
{
|
||||
CompileExternItem::compile (item.get (), ctx, concrete);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompileItem::visit (HIR::Module &module)
|
||||
{
|
||||
for (auto &item : module.get_items ())
|
||||
CompileItem::compile (item.get (), ctx);
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
88
gcc/rust/backend/rust-compile-item.h
Normal file
88
gcc/rust/backend/rust-compile-item.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_ITEM
|
||||
#define RUST_COMPILE_ITEM
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileItem : private HIRCompileBase, protected HIR::HIRStmtVisitor
|
||||
{
|
||||
protected:
|
||||
public:
|
||||
static tree compile (HIR::Item *item, Context *ctx,
|
||||
TyTy::BaseType *concrete = nullptr,
|
||||
bool is_query_mode = false,
|
||||
Location ref_locus = Location ())
|
||||
{
|
||||
CompileItem compiler (ctx, concrete, ref_locus);
|
||||
item->accept_vis (compiler);
|
||||
|
||||
if (is_query_mode && compiler.reference == error_mark_node)
|
||||
rust_internal_error_at (ref_locus, "failed to compile item: %s",
|
||||
item->as_string ().c_str ());
|
||||
|
||||
return compiler.reference;
|
||||
}
|
||||
|
||||
void visit (HIR::StaticItem &var) override;
|
||||
void visit (HIR::ConstantItem &constant) override;
|
||||
void visit (HIR::Function &function) override;
|
||||
void visit (HIR::ImplBlock &impl_block) override;
|
||||
void visit (HIR::ExternBlock &extern_block) override;
|
||||
void visit (HIR::Module &module) override;
|
||||
|
||||
// Empty visit for unused Stmt HIR nodes.
|
||||
void visit (HIR::TupleStruct &) override {}
|
||||
void visit (HIR::EnumItem &) override {}
|
||||
void visit (HIR::EnumItemTuple &) override {}
|
||||
void visit (HIR::EnumItemStruct &) override {}
|
||||
void visit (HIR::EnumItemDiscriminant &) override {}
|
||||
void visit (HIR::TypePathSegmentFunction &) override {}
|
||||
void visit (HIR::TypePath &) override {}
|
||||
void visit (HIR::QualifiedPathInType &) override {}
|
||||
void visit (HIR::ExternCrate &) override {}
|
||||
void visit (HIR::UseDeclaration &) override {}
|
||||
void visit (HIR::TypeAlias &) override {}
|
||||
void visit (HIR::StructStruct &) override {}
|
||||
void visit (HIR::Enum &) override {}
|
||||
void visit (HIR::Union &) override {}
|
||||
void visit (HIR::Trait &) override {}
|
||||
void visit (HIR::EmptyStmt &) override {}
|
||||
void visit (HIR::LetStmt &) override {}
|
||||
void visit (HIR::ExprStmtWithoutBlock &) override {}
|
||||
void visit (HIR::ExprStmtWithBlock &) override {}
|
||||
|
||||
protected:
|
||||
CompileItem (Context *ctx, TyTy::BaseType *concrete, Location ref_locus)
|
||||
: HIRCompileBase (ctx), concrete (concrete), reference (error_mark_node),
|
||||
ref_locus (ref_locus)
|
||||
{}
|
||||
|
||||
TyTy::BaseType *concrete;
|
||||
tree reference;
|
||||
Location ref_locus;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_ITEM
|
||||
333
gcc/rust/backend/rust-compile-pattern.cc
Normal file
333
gcc/rust/backend/rust-compile-pattern.cc
Normal file
@@ -0,0 +1,333 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-pattern.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-compile-resolve-path.h"
|
||||
#include "rust-constexpr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::PathInExpression &pattern)
|
||||
{
|
||||
// lookup the type
|
||||
TyTy::BaseType *lookup = nullptr;
|
||||
bool ok
|
||||
= ctx->get_tyctx ()->lookup_type (pattern.get_mappings ().get_hirid (),
|
||||
&lookup);
|
||||
rust_assert (ok);
|
||||
|
||||
// this must be an enum
|
||||
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
|
||||
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
|
||||
rust_assert (adt->is_enum ());
|
||||
|
||||
// lookup the variant
|
||||
HirId variant_id;
|
||||
ok = ctx->get_tyctx ()->lookup_variant_definition (
|
||||
pattern.get_mappings ().get_hirid (), &variant_id);
|
||||
rust_assert (ok);
|
||||
|
||||
TyTy::VariantDef *variant = nullptr;
|
||||
ok = adt->lookup_variant_by_id (variant_id, &variant);
|
||||
rust_assert (ok);
|
||||
|
||||
HIR::Expr *discrim_expr = variant->get_discriminant ();
|
||||
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
|
||||
tree folded_discrim_expr = fold_expr (discrim_expr_node);
|
||||
tree case_low = folded_discrim_expr;
|
||||
|
||||
case_label_expr
|
||||
= build_case_label (case_low, NULL_TREE, associated_case_label);
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::StructPattern &pattern)
|
||||
{
|
||||
CompilePatternCaseLabelExpr::visit (pattern.get_path ());
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::TupleStructPattern &pattern)
|
||||
{
|
||||
CompilePatternCaseLabelExpr::visit (pattern.get_path ());
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::WildcardPattern &pattern)
|
||||
{
|
||||
// operand 0 being NULL_TREE signifies this is the default case label see:
|
||||
// tree.def for documentation for CASE_LABEL_EXPR
|
||||
case_label_expr
|
||||
= build_case_label (NULL_TREE, NULL_TREE, associated_case_label);
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::LiteralPattern &pattern)
|
||||
{
|
||||
// Compile the literal
|
||||
HIR::LiteralExpr *litexpr
|
||||
= new HIR::LiteralExpr (pattern.get_pattern_mappings (),
|
||||
pattern.get_literal (), pattern.get_locus (),
|
||||
std::vector<AST::Attribute> ());
|
||||
|
||||
// Note: Floating point literals are currently accepted but will likely be
|
||||
// forbidden in LiteralPatterns in a future version of Rust.
|
||||
// See: https://github.com/rust-lang/rust/issues/41620
|
||||
// For now, we cannot compile them anyway as CASE_LABEL_EXPR does not support
|
||||
// floating point types.
|
||||
if (pattern.get_literal ().get_lit_type () == HIR::Literal::LitType::FLOAT)
|
||||
{
|
||||
rust_sorry_at (pattern.get_locus (), "floating-point literal in pattern");
|
||||
}
|
||||
|
||||
tree lit = CompileExpr::Compile (litexpr, ctx);
|
||||
|
||||
case_label_expr = build_case_label (lit, NULL_TREE, associated_case_label);
|
||||
}
|
||||
|
||||
static tree
|
||||
compile_range_pattern_bound (HIR::RangePatternBound *bound,
|
||||
Analysis::NodeMapping mappings, Location locus,
|
||||
Context *ctx)
|
||||
{
|
||||
tree result = NULL_TREE;
|
||||
switch (bound->get_bound_type ())
|
||||
{
|
||||
case HIR::RangePatternBound::RangePatternBoundType::LITERAL: {
|
||||
HIR::RangePatternBoundLiteral &ref
|
||||
= *static_cast<HIR::RangePatternBoundLiteral *> (bound);
|
||||
|
||||
HIR::LiteralExpr *litexpr
|
||||
= new HIR::LiteralExpr (mappings, ref.get_literal (), locus,
|
||||
std::vector<AST::Attribute> ());
|
||||
|
||||
result = CompileExpr::Compile (litexpr, ctx);
|
||||
}
|
||||
break;
|
||||
|
||||
case HIR::RangePatternBound::RangePatternBoundType::PATH: {
|
||||
HIR::RangePatternBoundPath &ref
|
||||
= *static_cast<HIR::RangePatternBoundPath *> (bound);
|
||||
|
||||
result = ResolvePathRef::Compile (ref.get_path (), ctx);
|
||||
|
||||
// If the path resolves to a const expression, fold it.
|
||||
result = fold_expr (result);
|
||||
}
|
||||
break;
|
||||
|
||||
case HIR::RangePatternBound::RangePatternBoundType::QUALPATH: {
|
||||
HIR::RangePatternBoundQualPath &ref
|
||||
= *static_cast<HIR::RangePatternBoundQualPath *> (bound);
|
||||
|
||||
result = ResolvePathRef::Compile (ref.get_qualified_path (), ctx);
|
||||
|
||||
// If the path resolves to a const expression, fold it.
|
||||
result = fold_expr (result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternCaseLabelExpr::visit (HIR::RangePattern &pattern)
|
||||
{
|
||||
tree upper = compile_range_pattern_bound (pattern.get_upper_bound ().get (),
|
||||
pattern.get_pattern_mappings (),
|
||||
pattern.get_locus (), ctx);
|
||||
tree lower = compile_range_pattern_bound (pattern.get_lower_bound ().get (),
|
||||
pattern.get_pattern_mappings (),
|
||||
pattern.get_locus (), ctx);
|
||||
|
||||
case_label_expr = build_case_label (lower, upper, associated_case_label);
|
||||
}
|
||||
|
||||
// setup the bindings
|
||||
|
||||
void
|
||||
CompilePatternBindings::visit (HIR::TupleStructPattern &pattern)
|
||||
{
|
||||
// lookup the type
|
||||
TyTy::BaseType *lookup = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||
pattern.get_path ().get_mappings ().get_hirid (), &lookup);
|
||||
rust_assert (ok);
|
||||
|
||||
// this must be an enum
|
||||
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
|
||||
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
|
||||
rust_assert (adt->number_of_variants () > 0);
|
||||
|
||||
int variant_index = 0;
|
||||
TyTy::VariantDef *variant = adt->get_variants ().at (0);
|
||||
if (adt->is_enum ())
|
||||
{
|
||||
HirId variant_id = UNKNOWN_HIRID;
|
||||
bool ok = ctx->get_tyctx ()->lookup_variant_definition (
|
||||
pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
|
||||
rust_assert (ok);
|
||||
|
||||
ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
|
||||
rust_assert (ok);
|
||||
}
|
||||
|
||||
rust_assert (variant->get_variant_type ()
|
||||
== TyTy::VariantDef::VariantType::TUPLE);
|
||||
|
||||
std::unique_ptr<HIR::TupleStructItems> &items = pattern.get_items ();
|
||||
switch (items->get_item_type ())
|
||||
{
|
||||
case HIR::TupleStructItems::RANGE: {
|
||||
// TODO
|
||||
gcc_unreachable ();
|
||||
}
|
||||
break;
|
||||
|
||||
case HIR::TupleStructItems::NO_RANGE: {
|
||||
HIR::TupleStructItemsNoRange &items_no_range
|
||||
= static_cast<HIR::TupleStructItemsNoRange &> (*items.get ());
|
||||
|
||||
rust_assert (items_no_range.get_patterns ().size ()
|
||||
== variant->num_fields ());
|
||||
|
||||
if (adt->is_enum ())
|
||||
{
|
||||
// we are offsetting by + 1 here since the first field in the record
|
||||
// is always the discriminator
|
||||
size_t tuple_field_index = 1;
|
||||
for (auto &pattern : items_no_range.get_patterns ())
|
||||
{
|
||||
tree variant_accessor
|
||||
= ctx->get_backend ()->struct_field_expression (
|
||||
match_scrutinee_expr, variant_index, pattern->get_locus ());
|
||||
|
||||
tree binding = ctx->get_backend ()->struct_field_expression (
|
||||
variant_accessor, tuple_field_index++, pattern->get_locus ());
|
||||
|
||||
ctx->insert_pattern_binding (
|
||||
pattern->get_pattern_mappings ().get_hirid (), binding);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t tuple_field_index = 0;
|
||||
for (auto &pattern : items_no_range.get_patterns ())
|
||||
{
|
||||
tree variant_accessor = match_scrutinee_expr;
|
||||
|
||||
tree binding = ctx->get_backend ()->struct_field_expression (
|
||||
variant_accessor, tuple_field_index++, pattern->get_locus ());
|
||||
|
||||
ctx->insert_pattern_binding (
|
||||
pattern->get_pattern_mappings ().get_hirid (), binding);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompilePatternBindings::visit (HIR::StructPattern &pattern)
|
||||
{
|
||||
// lookup the type
|
||||
TyTy::BaseType *lookup = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||
pattern.get_path ().get_mappings ().get_hirid (), &lookup);
|
||||
rust_assert (ok);
|
||||
|
||||
// this must be an enum
|
||||
rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
|
||||
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
|
||||
rust_assert (adt->number_of_variants () > 0);
|
||||
|
||||
int variant_index = 0;
|
||||
TyTy::VariantDef *variant = adt->get_variants ().at (0);
|
||||
if (adt->is_enum ())
|
||||
{
|
||||
HirId variant_id = UNKNOWN_HIRID;
|
||||
bool ok = ctx->get_tyctx ()->lookup_variant_definition (
|
||||
pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
|
||||
rust_assert (ok);
|
||||
|
||||
ok = adt->lookup_variant_by_id (variant_id, &variant, &variant_index);
|
||||
rust_assert (ok);
|
||||
}
|
||||
|
||||
rust_assert (variant->get_variant_type ()
|
||||
== TyTy::VariantDef::VariantType::STRUCT);
|
||||
|
||||
auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
|
||||
for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
|
||||
{
|
||||
switch (field->get_item_type ())
|
||||
{
|
||||
case HIR::StructPatternField::ItemType::TUPLE_PAT: {
|
||||
// TODO
|
||||
gcc_unreachable ();
|
||||
}
|
||||
break;
|
||||
|
||||
case HIR::StructPatternField::ItemType::IDENT_PAT: {
|
||||
// TODO
|
||||
gcc_unreachable ();
|
||||
}
|
||||
break;
|
||||
|
||||
case HIR::StructPatternField::ItemType::IDENT: {
|
||||
HIR::StructPatternFieldIdent &ident
|
||||
= static_cast<HIR::StructPatternFieldIdent &> (*field.get ());
|
||||
|
||||
size_t offs = 0;
|
||||
ok
|
||||
= variant->lookup_field (ident.get_identifier (), nullptr, &offs);
|
||||
rust_assert (ok);
|
||||
|
||||
tree binding = error_mark_node;
|
||||
if (adt->is_enum ())
|
||||
{
|
||||
tree variant_accessor
|
||||
= ctx->get_backend ()->struct_field_expression (
|
||||
match_scrutinee_expr, variant_index, ident.get_locus ());
|
||||
|
||||
// we are offsetting by + 1 here since the first field in the
|
||||
// record is always the discriminator
|
||||
binding = ctx->get_backend ()->struct_field_expression (
|
||||
variant_accessor, offs + 1, ident.get_locus ());
|
||||
}
|
||||
else
|
||||
{
|
||||
tree variant_accessor = match_scrutinee_expr;
|
||||
binding = ctx->get_backend ()->struct_field_expression (
|
||||
variant_accessor, offs, ident.get_locus ());
|
||||
}
|
||||
|
||||
ctx->insert_pattern_binding (ident.get_mappings ().get_hirid (),
|
||||
binding);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
95
gcc/rust/backend/rust-compile-pattern.h
Normal file
95
gcc/rust/backend/rust-compile-pattern.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompilePatternCaseLabelExpr : public HIRCompileBase,
|
||||
public HIR::HIRPatternVisitor
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::Pattern *pattern, tree associated_case_label,
|
||||
Context *ctx)
|
||||
{
|
||||
CompilePatternCaseLabelExpr compiler (ctx, associated_case_label);
|
||||
pattern->accept_vis (compiler);
|
||||
return compiler.case_label_expr;
|
||||
}
|
||||
|
||||
void visit (HIR::PathInExpression &pattern) override;
|
||||
void visit (HIR::StructPattern &pattern) override;
|
||||
void visit (HIR::TupleStructPattern &pattern) override;
|
||||
void visit (HIR::WildcardPattern &pattern) override;
|
||||
void visit (HIR::RangePattern &pattern) override;
|
||||
|
||||
// Empty visit for unused Pattern HIR nodes.
|
||||
void visit (HIR::GroupedPattern &) override {}
|
||||
void visit (HIR::IdentifierPattern &) override {}
|
||||
void visit (HIR::LiteralPattern &) override;
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::ReferencePattern &) override {}
|
||||
void visit (HIR::SlicePattern &) override {}
|
||||
void visit (HIR::TuplePattern &) override {}
|
||||
|
||||
CompilePatternCaseLabelExpr (Context *ctx, tree associated_case_label)
|
||||
: HIRCompileBase (ctx), case_label_expr (error_mark_node),
|
||||
associated_case_label (associated_case_label)
|
||||
{}
|
||||
|
||||
tree case_label_expr;
|
||||
tree associated_case_label;
|
||||
};
|
||||
|
||||
class CompilePatternBindings : public HIRCompileBase,
|
||||
public HIR::HIRPatternVisitor
|
||||
{
|
||||
public:
|
||||
static void Compile (HIR::Pattern *pattern, tree match_scrutinee_expr,
|
||||
Context *ctx)
|
||||
{
|
||||
CompilePatternBindings compiler (ctx, match_scrutinee_expr);
|
||||
pattern->accept_vis (compiler);
|
||||
}
|
||||
|
||||
void visit (HIR::StructPattern &pattern) override;
|
||||
void visit (HIR::TupleStructPattern &pattern) override;
|
||||
|
||||
// Empty visit for unused Pattern HIR nodes.
|
||||
void visit (HIR::GroupedPattern &) override {}
|
||||
void visit (HIR::IdentifierPattern &) override {}
|
||||
void visit (HIR::LiteralPattern &) override {}
|
||||
void visit (HIR::PathInExpression &) override {}
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::RangePattern &) override {}
|
||||
void visit (HIR::ReferencePattern &) override {}
|
||||
void visit (HIR::SlicePattern &) override {}
|
||||
void visit (HIR::TuplePattern &) override {}
|
||||
void visit (HIR::WildcardPattern &) override {}
|
||||
|
||||
protected:
|
||||
CompilePatternBindings (Context *ctx, tree match_scrutinee_expr)
|
||||
: HIRCompileBase (ctx), match_scrutinee_expr (match_scrutinee_expr)
|
||||
{}
|
||||
|
||||
tree match_scrutinee_expr;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
301
gcc/rust/backend/rust-compile-resolve-path.cc
Normal file
301
gcc/rust/backend/rust-compile-resolve-path.cc
Normal file
@@ -0,0 +1,301 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-resolve-path.h"
|
||||
#include "rust-compile-intrinsic.h"
|
||||
#include "rust-compile-item.h"
|
||||
#include "rust-compile-implitem.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-hir-trait-resolve.h"
|
||||
#include "rust-hir-path-probe.h"
|
||||
#include "rust-compile-extern.h"
|
||||
#include "rust-constexpr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
void
|
||||
ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr)
|
||||
{
|
||||
resolved = resolve (expr.get_final_segment ().get_segment (),
|
||||
expr.get_mappings (), expr.get_locus (), true);
|
||||
}
|
||||
|
||||
void
|
||||
ResolvePathRef::visit (HIR::PathInExpression &expr)
|
||||
{
|
||||
resolved = resolve (expr.get_final_segment ().get_segment (),
|
||||
expr.get_mappings (), expr.get_locus (), false);
|
||||
}
|
||||
|
||||
tree
|
||||
ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
|
||||
const Analysis::NodeMapping &mappings,
|
||||
Location expr_locus, bool is_qualified_path)
|
||||
{
|
||||
TyTy::BaseType *lookup = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
|
||||
rust_assert (ok);
|
||||
|
||||
// need to look up the reference for this identifier
|
||||
NodeId ref_node_id = UNKNOWN_NODEID;
|
||||
if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
|
||||
&ref_node_id))
|
||||
{
|
||||
// this can fail because it might be a Constructor for something
|
||||
// in that case the caller should attempt ResolvePathType::Compile
|
||||
|
||||
// it might be an enum data-less enum variant
|
||||
if (lookup->get_kind () != TyTy::TypeKind::ADT)
|
||||
return error_mark_node;
|
||||
|
||||
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
|
||||
|
||||
// it might be a unit-struct
|
||||
if (adt->is_unit ())
|
||||
{
|
||||
return ctx->get_backend ()->unit_expression ();
|
||||
}
|
||||
|
||||
if (!adt->is_enum ())
|
||||
return error_mark_node;
|
||||
|
||||
HirId variant_id;
|
||||
if (!ctx->get_tyctx ()->lookup_variant_definition (mappings.get_hirid (),
|
||||
&variant_id))
|
||||
return error_mark_node;
|
||||
|
||||
int union_disriminator = -1;
|
||||
TyTy::VariantDef *variant = nullptr;
|
||||
if (!adt->lookup_variant_by_id (variant_id, &variant,
|
||||
&union_disriminator))
|
||||
return error_mark_node;
|
||||
|
||||
// this can only be for discriminant variants the others are built up
|
||||
// using call-expr or struct-init
|
||||
rust_assert (variant->get_variant_type ()
|
||||
== TyTy::VariantDef::VariantType::NUM);
|
||||
|
||||
// we need the actual gcc type
|
||||
tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
|
||||
|
||||
// make the ctor for the union
|
||||
HIR::Expr *discrim_expr = variant->get_discriminant ();
|
||||
tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
|
||||
tree folded_discrim_expr = fold_expr (discrim_expr_node);
|
||||
tree qualifier = folded_discrim_expr;
|
||||
|
||||
return ctx->get_backend ()->constructor_expression (compiled_adt_type,
|
||||
true, {qualifier},
|
||||
union_disriminator,
|
||||
expr_locus);
|
||||
}
|
||||
|
||||
HirId ref;
|
||||
if (!ctx->get_mappings ()->lookup_node_to_hir (ref_node_id, &ref))
|
||||
{
|
||||
rust_error_at (expr_locus, "reverse call path lookup failure");
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
// might be a constant
|
||||
tree constant_expr;
|
||||
if (ctx->lookup_const_decl (ref, &constant_expr))
|
||||
{
|
||||
TREE_USED (constant_expr) = 1;
|
||||
return constant_expr;
|
||||
}
|
||||
|
||||
// this might be a variable reference or a function reference
|
||||
Bvariable *var = nullptr;
|
||||
if (ctx->lookup_var_decl (ref, &var))
|
||||
{
|
||||
// TREE_USED is setup in the gcc abstraction here
|
||||
return ctx->get_backend ()->var_expression (var, expr_locus);
|
||||
}
|
||||
|
||||
// might be a match pattern binding
|
||||
tree binding = error_mark_node;
|
||||
if (ctx->lookup_pattern_binding (ref, &binding))
|
||||
{
|
||||
TREE_USED (binding) = 1;
|
||||
return binding;
|
||||
}
|
||||
|
||||
// it might be a function call
|
||||
if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
|
||||
{
|
||||
TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
|
||||
tree fn = NULL_TREE;
|
||||
if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
|
||||
{
|
||||
TREE_USED (fn) = 1;
|
||||
return address_expression (fn, expr_locus);
|
||||
}
|
||||
else if (fntype->get_abi () == ABI::INTRINSIC)
|
||||
{
|
||||
Intrinsics compile (ctx);
|
||||
fn = compile.compile (fntype);
|
||||
TREE_USED (fn) = 1;
|
||||
return address_expression (fn, expr_locus);
|
||||
}
|
||||
}
|
||||
|
||||
// let the query system figure it out
|
||||
tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
|
||||
expr_locus, is_qualified_path);
|
||||
if (resolved_item != error_mark_node)
|
||||
{
|
||||
TREE_USED (resolved_item) = 1;
|
||||
}
|
||||
return resolved_item;
|
||||
}
|
||||
|
||||
tree
|
||||
HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
|
||||
const HIR::PathIdentSegment &final_segment,
|
||||
const Analysis::NodeMapping &mappings,
|
||||
Location expr_locus, bool is_qualified_path)
|
||||
{
|
||||
HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (ref);
|
||||
HirId parent_block;
|
||||
HIR::ExternalItem *resolved_extern_item
|
||||
= ctx->get_mappings ()->lookup_hir_extern_item (ref, &parent_block);
|
||||
bool is_hir_item = resolved_item != nullptr;
|
||||
bool is_hir_extern_item = resolved_extern_item != nullptr;
|
||||
if (is_hir_item)
|
||||
{
|
||||
if (!lookup->has_subsititions_defined ())
|
||||
return CompileItem::compile (resolved_item, ctx, nullptr, true,
|
||||
expr_locus);
|
||||
else
|
||||
return CompileItem::compile (resolved_item, ctx, lookup, true,
|
||||
expr_locus);
|
||||
}
|
||||
else if (is_hir_extern_item)
|
||||
{
|
||||
if (!lookup->has_subsititions_defined ())
|
||||
return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
|
||||
true, expr_locus);
|
||||
else
|
||||
return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
|
||||
true, expr_locus);
|
||||
}
|
||||
else
|
||||
{
|
||||
HirId parent_impl_id = UNKNOWN_HIRID;
|
||||
HIR::ImplItem *resolved_item
|
||||
= ctx->get_mappings ()->lookup_hir_implitem (ref, &parent_impl_id);
|
||||
bool is_impl_item = resolved_item != nullptr;
|
||||
if (is_impl_item)
|
||||
{
|
||||
rust_assert (parent_impl_id != UNKNOWN_HIRID);
|
||||
HIR::Item *impl_ref
|
||||
= ctx->get_mappings ()->lookup_hir_item (parent_impl_id);
|
||||
rust_assert (impl_ref != nullptr);
|
||||
HIR::ImplBlock *impl = static_cast<HIR::ImplBlock *> (impl_ref);
|
||||
|
||||
TyTy::BaseType *self = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||
impl->get_type ()->get_mappings ().get_hirid (), &self);
|
||||
rust_assert (ok);
|
||||
|
||||
if (!lookup->has_subsititions_defined ())
|
||||
return CompileInherentImplItem::Compile (resolved_item, ctx,
|
||||
nullptr, true, expr_locus);
|
||||
else
|
||||
return CompileInherentImplItem::Compile (resolved_item, ctx, lookup,
|
||||
true, expr_locus);
|
||||
}
|
||||
else
|
||||
{
|
||||
// it might be resolved to a trait item
|
||||
HIR::TraitItem *trait_item
|
||||
= ctx->get_mappings ()->lookup_hir_trait_item (ref);
|
||||
HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
|
||||
trait_item->get_mappings ().get_hirid ());
|
||||
|
||||
Resolver::TraitReference *trait_ref
|
||||
= &Resolver::TraitReference::error_node ();
|
||||
bool ok = ctx->get_tyctx ()->lookup_trait_reference (
|
||||
trait->get_mappings ().get_defid (), &trait_ref);
|
||||
rust_assert (ok);
|
||||
|
||||
TyTy::BaseType *receiver = nullptr;
|
||||
ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (),
|
||||
&receiver);
|
||||
rust_assert (ok);
|
||||
|
||||
if (receiver->get_kind () == TyTy::TypeKind::PARAM)
|
||||
{
|
||||
TyTy::ParamType *p = static_cast<TyTy::ParamType *> (receiver);
|
||||
receiver = p->resolve ();
|
||||
}
|
||||
|
||||
// the type resolver can only resolve type bounds to their trait
|
||||
// item so its up to us to figure out if this path should resolve
|
||||
// to an trait-impl-block-item or if it can be defaulted to the
|
||||
// trait-impl-item's definition
|
||||
std::vector<Resolver::PathProbeCandidate> candidates
|
||||
= Resolver::PathProbeImplTrait::Probe (receiver, final_segment,
|
||||
trait_ref);
|
||||
if (candidates.size () == 0)
|
||||
{
|
||||
// this means we are defaulting back to the trait_item if
|
||||
// possible
|
||||
Resolver::TraitItemReference *trait_item_ref = nullptr;
|
||||
bool ok = trait_ref->lookup_hir_trait_item (*trait_item,
|
||||
&trait_item_ref);
|
||||
rust_assert (ok); // found
|
||||
rust_assert (trait_item_ref->is_optional ()); // has definition
|
||||
|
||||
return CompileTraitItem::Compile (
|
||||
trait_item_ref->get_hir_trait_item (), ctx, lookup, true,
|
||||
expr_locus);
|
||||
}
|
||||
else
|
||||
{
|
||||
Resolver::PathProbeCandidate &candidate = candidates.at (0);
|
||||
rust_assert (candidate.is_impl_candidate ());
|
||||
|
||||
HIR::ImplBlock *impl = candidate.item.impl.parent;
|
||||
HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
|
||||
|
||||
TyTy::BaseType *self = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||
impl->get_type ()->get_mappings ().get_hirid (), &self);
|
||||
rust_assert (ok);
|
||||
|
||||
if (!lookup->has_subsititions_defined ())
|
||||
return CompileInherentImplItem::Compile (impl_item, ctx,
|
||||
nullptr, true,
|
||||
expr_locus);
|
||||
else
|
||||
return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
|
||||
true, expr_locus);
|
||||
|
||||
lookup->set_ty_ref (impl_item->get_impl_mappings ().get_hirid ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error_mark_node;
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
73
gcc/rust/backend/rust-compile-resolve-path.h
Normal file
73
gcc/rust/backend/rust-compile-resolve-path.h
Normal file
@@ -0,0 +1,73 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_RESOLVE_PATH
|
||||
#define RUST_COMPILE_RESOLVE_PATH
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class ResolvePathRef : public HIRCompileBase, public HIR::HIRPatternVisitor
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::QualifiedPathInExpression &expr, Context *ctx)
|
||||
{
|
||||
ResolvePathRef resolver (ctx);
|
||||
expr.accept_vis (resolver);
|
||||
return resolver.resolved;
|
||||
}
|
||||
|
||||
static tree Compile (HIR::PathInExpression &expr, Context *ctx)
|
||||
{
|
||||
ResolvePathRef resolver (ctx);
|
||||
expr.accept_vis (resolver);
|
||||
return resolver.resolved;
|
||||
}
|
||||
|
||||
void visit (HIR::PathInExpression &expr) override;
|
||||
void visit (HIR::QualifiedPathInExpression &expr) override;
|
||||
|
||||
// Empty visit for unused Pattern HIR nodes.
|
||||
void visit (HIR::GroupedPattern &) override {}
|
||||
void visit (HIR::IdentifierPattern &) override {}
|
||||
void visit (HIR::LiteralPattern &) override {}
|
||||
void visit (HIR::RangePattern &) override {}
|
||||
void visit (HIR::ReferencePattern &) override {}
|
||||
void visit (HIR::SlicePattern &) override {}
|
||||
void visit (HIR::StructPattern &) override {}
|
||||
void visit (HIR::TuplePattern &) override {}
|
||||
void visit (HIR::TupleStructPattern &) override {}
|
||||
void visit (HIR::WildcardPattern &) override {}
|
||||
|
||||
ResolvePathRef (Context *ctx)
|
||||
: HIRCompileBase (ctx), resolved (error_mark_node)
|
||||
{}
|
||||
|
||||
tree resolve (const HIR::PathIdentSegment &final_segment,
|
||||
const Analysis::NodeMapping &mappings, Location locus,
|
||||
bool is_qualified_path);
|
||||
|
||||
tree resolved;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_RESOLVE_PATH
|
||||
115
gcc/rust/backend/rust-compile-stmt.cc
Normal file
115
gcc/rust/backend/rust-compile-stmt.cc
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-stmt.h"
|
||||
#include "rust-compile-expr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
CompileStmt::CompileStmt (Context *ctx)
|
||||
: HIRCompileBase (ctx), translated (nullptr)
|
||||
{}
|
||||
|
||||
tree
|
||||
CompileStmt::Compile (HIR::Stmt *stmt, Context *ctx)
|
||||
{
|
||||
CompileStmt compiler (ctx);
|
||||
stmt->accept_vis (compiler);
|
||||
return compiler.translated;
|
||||
}
|
||||
|
||||
void
|
||||
CompileStmt::visit (HIR::ExprStmtWithBlock &stmt)
|
||||
{
|
||||
translated = CompileExpr::Compile (stmt.get_expr (), ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileStmt::visit (HIR::ExprStmtWithoutBlock &stmt)
|
||||
{
|
||||
translated = CompileExpr::Compile (stmt.get_expr (), ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileStmt::visit (HIR::LetStmt &stmt)
|
||||
{
|
||||
// nothing to do
|
||||
if (!stmt.has_init_expr ())
|
||||
return;
|
||||
|
||||
const HIR::Pattern &stmt_pattern = *stmt.get_pattern ();
|
||||
HirId stmt_id = stmt_pattern.get_pattern_mappings ().get_hirid ();
|
||||
|
||||
TyTy::BaseType *ty = nullptr;
|
||||
if (!ctx->get_tyctx ()->lookup_type (stmt_id, &ty))
|
||||
{
|
||||
// FIXME this should be an assertion instead
|
||||
rust_fatal_error (stmt.get_locus (),
|
||||
"failed to lookup variable declaration type");
|
||||
return;
|
||||
}
|
||||
|
||||
Bvariable *var = nullptr;
|
||||
if (!ctx->lookup_var_decl (stmt_id, &var))
|
||||
{
|
||||
// FIXME this should be an assertion instead and use error mark node
|
||||
rust_fatal_error (stmt.get_locus (),
|
||||
"failed to lookup compiled variable declaration");
|
||||
return;
|
||||
}
|
||||
|
||||
tree init = CompileExpr::Compile (stmt.get_init_expr (), ctx);
|
||||
// FIXME use error_mark_node, check that CompileExpr returns error_mark_node
|
||||
// on failure and make this an assertion
|
||||
if (init == nullptr)
|
||||
return;
|
||||
|
||||
TyTy::BaseType *actual = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_type (
|
||||
stmt.get_init_expr ()->get_mappings ().get_hirid (), &actual);
|
||||
rust_assert (ok);
|
||||
tree stmt_type = TyTyResolveCompile::compile (ctx, ty);
|
||||
|
||||
Location lvalue_locus = stmt.get_pattern ()->get_locus ();
|
||||
Location rvalue_locus = stmt.get_init_expr ()->get_locus ();
|
||||
TyTy::BaseType *expected = ty;
|
||||
init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual,
|
||||
expected, lvalue_locus, rvalue_locus);
|
||||
|
||||
auto fnctx = ctx->peek_fn ();
|
||||
if (ty->is_unit ())
|
||||
{
|
||||
ctx->add_statement (init);
|
||||
|
||||
auto unit_type_init_expr
|
||||
= ctx->get_backend ()->constructor_expression (stmt_type, false, {}, -1,
|
||||
rvalue_locus);
|
||||
auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var,
|
||||
unit_type_init_expr);
|
||||
ctx->add_statement (s);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init);
|
||||
ctx->add_statement (s);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
69
gcc/rust/backend/rust-compile-stmt.h
Normal file
69
gcc/rust/backend/rust-compile-stmt.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_STMT
|
||||
#define RUST_COMPILE_STMT
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileStmt : private HIRCompileBase, protected HIR::HIRStmtVisitor
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::Stmt *stmt, Context *ctx);
|
||||
|
||||
void visit (HIR::ExprStmtWithBlock &stmt) override;
|
||||
void visit (HIR::ExprStmtWithoutBlock &stmt) override;
|
||||
void visit (HIR::LetStmt &stmt) override;
|
||||
|
||||
// Empty visit for unused Stmt HIR nodes.
|
||||
void visit (HIR::TupleStruct &) override {}
|
||||
void visit (HIR::EnumItem &) override {}
|
||||
void visit (HIR::EnumItemTuple &) override {}
|
||||
void visit (HIR::EnumItemStruct &) override {}
|
||||
void visit (HIR::EnumItemDiscriminant &) override {}
|
||||
void visit (HIR::TypePathSegmentFunction &) override {}
|
||||
void visit (HIR::TypePath &) override {}
|
||||
void visit (HIR::QualifiedPathInType &) override {}
|
||||
void visit (HIR::Module &) override {}
|
||||
void visit (HIR::ExternCrate &) override {}
|
||||
void visit (HIR::UseDeclaration &) override {}
|
||||
void visit (HIR::Function &) override {}
|
||||
void visit (HIR::TypeAlias &) override {}
|
||||
void visit (HIR::StructStruct &) override {}
|
||||
void visit (HIR::Enum &) override {}
|
||||
void visit (HIR::Union &) override {}
|
||||
void visit (HIR::ConstantItem &) override {}
|
||||
void visit (HIR::StaticItem &) override {}
|
||||
void visit (HIR::Trait &) override {}
|
||||
void visit (HIR::ImplBlock &) override {}
|
||||
void visit (HIR::ExternBlock &) override {}
|
||||
void visit (HIR::EmptyStmt &) override {}
|
||||
|
||||
private:
|
||||
CompileStmt (Context *ctx);
|
||||
|
||||
tree translated;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_STMT
|
||||
81
gcc/rust/backend/rust-compile-struct-field-expr.cc
Normal file
81
gcc/rust/backend/rust-compile-struct-field-expr.cc
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-struct-field-expr.h"
|
||||
#include "rust-compile-expr.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
CompileStructExprField::CompileStructExprField (Context *ctx)
|
||||
: HIRCompileBase (ctx), translated (error_mark_node)
|
||||
{}
|
||||
|
||||
tree
|
||||
CompileStructExprField::Compile (HIR::StructExprField *field, Context *ctx)
|
||||
{
|
||||
CompileStructExprField compiler (ctx);
|
||||
switch (field->get_kind ())
|
||||
{
|
||||
case HIR::StructExprField::StructExprFieldKind::IDENTIFIER:
|
||||
compiler.visit (static_cast<HIR::StructExprFieldIdentifier &> (*field));
|
||||
break;
|
||||
|
||||
case HIR::StructExprField::StructExprFieldKind::IDENTIFIER_VALUE:
|
||||
compiler.visit (
|
||||
static_cast<HIR::StructExprFieldIdentifierValue &> (*field));
|
||||
break;
|
||||
|
||||
case HIR::StructExprField::StructExprFieldKind::INDEX_VALUE:
|
||||
compiler.visit (static_cast<HIR::StructExprFieldIndexValue &> (*field));
|
||||
break;
|
||||
}
|
||||
return compiler.translated;
|
||||
}
|
||||
|
||||
void
|
||||
CompileStructExprField::visit (HIR::StructExprFieldIdentifierValue &field)
|
||||
{
|
||||
translated = CompileExpr::Compile (field.get_value (), ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileStructExprField::visit (HIR::StructExprFieldIndexValue &field)
|
||||
{
|
||||
translated = CompileExpr::Compile (field.get_value (), ctx);
|
||||
}
|
||||
|
||||
void
|
||||
CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field)
|
||||
{
|
||||
// we can make the field look like a path expr to take advantage of existing
|
||||
// code
|
||||
|
||||
Analysis::NodeMapping mappings_copy1 = field.get_mappings ();
|
||||
Analysis::NodeMapping mappings_copy2 = field.get_mappings ();
|
||||
|
||||
HIR::PathIdentSegment ident_seg (field.get_field_name ());
|
||||
HIR::PathExprSegment seg (mappings_copy1, ident_seg, field.get_locus (),
|
||||
HIR::GenericArgs::create_empty ());
|
||||
HIR::PathInExpression expr (mappings_copy2, {seg}, field.get_locus (), false,
|
||||
{});
|
||||
translated = CompileExpr::Compile (&expr, ctx);
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
46
gcc/rust/backend/rust-compile-struct-field-expr.h
Normal file
46
gcc/rust/backend/rust-compile-struct-field-expr.h
Normal file
@@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_STRUCT_FIELD_EXPR
|
||||
#define RUST_COMPILE_STRUCT_FIELD_EXPR
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileStructExprField : private HIRCompileBase
|
||||
{
|
||||
public:
|
||||
static tree Compile (HIR::StructExprField *field, Context *ctx);
|
||||
|
||||
protected:
|
||||
void visit (HIR::StructExprFieldIdentifierValue &field);
|
||||
void visit (HIR::StructExprFieldIndexValue &field);
|
||||
void visit (HIR::StructExprFieldIdentifier &field);
|
||||
|
||||
private:
|
||||
CompileStructExprField (Context *ctx);
|
||||
|
||||
tree translated;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_STRUCT_FIELD_EXPR
|
||||
713
gcc/rust/backend/rust-compile-type.cc
Normal file
713
gcc/rust/backend/rust-compile-type.cc
Normal file
@@ -0,0 +1,713 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "rust-compile-type.h"
|
||||
#include "rust-compile-expr.h"
|
||||
#include "rust-constexpr.h"
|
||||
|
||||
#include "tree.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
static const std::string RUST_ENUM_DISR_FIELD_NAME = "RUST$ENUM$DISR";
|
||||
|
||||
TyTyResolveCompile::TyTyResolveCompile (Context *ctx, bool trait_object_mode)
|
||||
: ctx (ctx), trait_object_mode (trait_object_mode),
|
||||
translated (error_mark_node), recurisve_ops (0)
|
||||
{}
|
||||
|
||||
tree
|
||||
TyTyResolveCompile::compile (Context *ctx, const TyTy::BaseType *ty,
|
||||
bool trait_object_mode)
|
||||
{
|
||||
TyTyResolveCompile compiler (ctx, trait_object_mode);
|
||||
ty->accept_vis (compiler);
|
||||
|
||||
if (compiler.translated != error_mark_node
|
||||
&& TYPE_NAME (compiler.translated) != NULL)
|
||||
{
|
||||
// canonicalize the type
|
||||
compiler.translated = ctx->insert_compiled_type (compiler.translated);
|
||||
}
|
||||
|
||||
return compiler.translated;
|
||||
}
|
||||
|
||||
// see: gcc/c/c-decl.cc:8230-8241
|
||||
// https://github.com/Rust-GCC/gccrs/blob/0024bc2f028369b871a65ceb11b2fddfb0f9c3aa/gcc/c/c-decl.c#L8229-L8241
|
||||
tree
|
||||
TyTyResolveCompile::get_implicit_enumeral_node_type (Context *ctx)
|
||||
{
|
||||
// static tree enum_node = NULL_TREE;
|
||||
// if (enum_node == NULL_TREE)
|
||||
// {
|
||||
// enum_node = make_node (ENUMERAL_TYPE);
|
||||
// SET_TYPE_MODE (enum_node, TYPE_MODE (unsigned_type_node));
|
||||
// SET_TYPE_ALIGN (enum_node, TYPE_ALIGN (unsigned_type_node));
|
||||
// TYPE_USER_ALIGN (enum_node) = 0;
|
||||
// TYPE_UNSIGNED (enum_node) = 1;
|
||||
// TYPE_PRECISION (enum_node) = TYPE_PRECISION (unsigned_type_node);
|
||||
// TYPE_MIN_VALUE (enum_node) = TYPE_MIN_VALUE (unsigned_type_node);
|
||||
// TYPE_MAX_VALUE (enum_node) = TYPE_MAX_VALUE (unsigned_type_node);
|
||||
|
||||
// // tree identifier = ctx->get_backend ()->get_identifier_node
|
||||
// // ("enumeral"); tree enum_decl
|
||||
// // = build_decl (BUILTINS_LOCATION, TYPE_DECL, identifier,
|
||||
// enum_node);
|
||||
// // TYPE_NAME (enum_node) = enum_decl;
|
||||
// }
|
||||
// return enum_node;
|
||||
|
||||
static tree enum_node = NULL_TREE;
|
||||
if (enum_node == NULL_TREE)
|
||||
{
|
||||
enum_node = ctx->get_backend ()->named_type (
|
||||
"enumeral", ctx->get_backend ()->integer_type (false, 64),
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
return enum_node;
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ErrorType &)
|
||||
{
|
||||
translated = error_mark_node;
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::InferType &)
|
||||
{
|
||||
translated = error_mark_node;
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ClosureType &)
|
||||
{
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ProjectionType &type)
|
||||
{
|
||||
type.get ()->accept_vis (*this);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::PlaceholderType &type)
|
||||
{
|
||||
type.resolve ()->accept_vis (*this);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ParamType ¶m)
|
||||
{
|
||||
if (recurisve_ops++ >= rust_max_recursion_depth)
|
||||
{
|
||||
rust_error_at (Location (),
|
||||
"%<recursion depth%> count exceeds limit of %i (use "
|
||||
"%<frust-max-recursion-depth=%> to increase the limit)",
|
||||
rust_max_recursion_depth);
|
||||
translated = error_mark_node;
|
||||
return;
|
||||
}
|
||||
|
||||
param.resolve ()->accept_vis (*this);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::FnType &type)
|
||||
{
|
||||
Backend::typed_identifier receiver;
|
||||
std::vector<Backend::typed_identifier> parameters;
|
||||
std::vector<Backend::typed_identifier> results;
|
||||
|
||||
if (!type.get_return_type ()->is_unit ())
|
||||
{
|
||||
auto hir_type = type.get_return_type ();
|
||||
auto ret = TyTyResolveCompile::compile (ctx, hir_type, trait_object_mode);
|
||||
results.push_back (Backend::typed_identifier (
|
||||
"_", ret,
|
||||
ctx->get_mappings ()->lookup_location (hir_type->get_ref ())));
|
||||
}
|
||||
|
||||
for (auto ¶m_pair : type.get_params ())
|
||||
{
|
||||
auto param_tyty = param_pair.second;
|
||||
auto compiled_param_type
|
||||
= TyTyResolveCompile::compile (ctx, param_tyty, trait_object_mode);
|
||||
|
||||
auto compiled_param = Backend::typed_identifier (
|
||||
param_pair.first->as_string (), compiled_param_type,
|
||||
ctx->get_mappings ()->lookup_location (param_tyty->get_ref ()));
|
||||
|
||||
parameters.push_back (compiled_param);
|
||||
}
|
||||
|
||||
if (!type.is_varadic ())
|
||||
translated
|
||||
= ctx->get_backend ()->function_type (receiver, parameters, results, NULL,
|
||||
type.get_ident ().locus);
|
||||
else
|
||||
translated
|
||||
= ctx->get_backend ()->function_type_varadic (receiver, parameters,
|
||||
results, NULL,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::FnPtr &type)
|
||||
{
|
||||
tree result_type = TyTyResolveCompile::compile (ctx, type.get_return_type ());
|
||||
|
||||
std::vector<tree> parameters;
|
||||
|
||||
auto ¶ms = type.get_params ();
|
||||
for (auto &p : params)
|
||||
{
|
||||
tree pty = TyTyResolveCompile::compile (ctx, p.get_tyty ());
|
||||
parameters.push_back (pty);
|
||||
}
|
||||
|
||||
translated = ctx->get_backend ()->function_ptr_type (result_type, parameters,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ADTType &type)
|
||||
{
|
||||
tree type_record = error_mark_node;
|
||||
if (!type.is_enum ())
|
||||
{
|
||||
rust_assert (type.number_of_variants () == 1);
|
||||
|
||||
TyTy::VariantDef &variant = *type.get_variants ().at (0);
|
||||
std::vector<Backend::typed_identifier> fields;
|
||||
for (size_t i = 0; i < variant.num_fields (); i++)
|
||||
{
|
||||
const TyTy::StructFieldType *field = variant.get_field_at_index (i);
|
||||
tree compiled_field_ty
|
||||
= TyTyResolveCompile::compile (ctx, field->get_field_type ());
|
||||
|
||||
Backend::typed_identifier f (field->get_name (), compiled_field_ty,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
type.get_ty_ref ()));
|
||||
fields.push_back (std::move (f));
|
||||
}
|
||||
|
||||
type_record = type.is_union ()
|
||||
? ctx->get_backend ()->union_type (fields)
|
||||
: ctx->get_backend ()->struct_type (fields);
|
||||
}
|
||||
else
|
||||
{
|
||||
// see:
|
||||
// https://github.com/bminor/binutils-gdb/blob/527b8861cd472385fa9160a91dd6d65a25c41987/gdb/dwarf2/read.c#L9010-L9241
|
||||
//
|
||||
// enums are actually a big union so for example the rust enum:
|
||||
//
|
||||
// enum AnEnum {
|
||||
// A,
|
||||
// B,
|
||||
// C (char),
|
||||
// D { x: i64, y: i64 },
|
||||
// }
|
||||
//
|
||||
// we actually turn this into
|
||||
//
|
||||
// union {
|
||||
// struct A { int RUST$ENUM$DISR; }; <- this is a data-less variant
|
||||
// struct B { int RUST$ENUM$DISR; }; <- this is a data-less variant
|
||||
// struct C { int RUST$ENUM$DISR; char __0; };
|
||||
// struct D { int RUST$ENUM$DISR; i64 x; i64 y; };
|
||||
// }
|
||||
//
|
||||
// Ada, qual_union_types might still work for this but I am not 100% sure.
|
||||
// I ran into some issues lets reuse our normal union and ask Ada people
|
||||
// about it.
|
||||
|
||||
std::vector<tree> variant_records;
|
||||
for (auto &variant : type.get_variants ())
|
||||
{
|
||||
std::vector<Backend::typed_identifier> fields;
|
||||
|
||||
// add in the qualifier field for the variant
|
||||
tree enumeral_type
|
||||
= TyTyResolveCompile::get_implicit_enumeral_node_type (ctx);
|
||||
Backend::typed_identifier f (RUST_ENUM_DISR_FIELD_NAME, enumeral_type,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
variant->get_id ()));
|
||||
fields.push_back (std::move (f));
|
||||
|
||||
// compile the rest of the fields
|
||||
for (size_t i = 0; i < variant->num_fields (); i++)
|
||||
{
|
||||
const TyTy::StructFieldType *field
|
||||
= variant->get_field_at_index (i);
|
||||
tree compiled_field_ty
|
||||
= TyTyResolveCompile::compile (ctx, field->get_field_type ());
|
||||
|
||||
std::string field_name = field->get_name ();
|
||||
if (variant->get_variant_type ()
|
||||
== TyTy::VariantDef::VariantType::TUPLE)
|
||||
field_name = "__" + field->get_name ();
|
||||
|
||||
Backend::typed_identifier f (
|
||||
field_name, compiled_field_ty,
|
||||
ctx->get_mappings ()->lookup_location (type.get_ty_ref ()));
|
||||
fields.push_back (std::move (f));
|
||||
}
|
||||
|
||||
tree variant_record = ctx->get_backend ()->struct_type (fields);
|
||||
tree named_variant_record = ctx->get_backend ()->named_type (
|
||||
variant->get_ident ().path.get (), variant_record,
|
||||
variant->get_ident ().locus);
|
||||
|
||||
// set the qualifier to be a builtin
|
||||
DECL_ARTIFICIAL (TYPE_FIELDS (variant_record)) = 1;
|
||||
|
||||
// add them to the list
|
||||
variant_records.push_back (named_variant_record);
|
||||
}
|
||||
|
||||
// now we need to make the actual union, but first we need to make
|
||||
// named_type TYPE_DECL's out of the variants
|
||||
|
||||
size_t i = 0;
|
||||
std::vector<Backend::typed_identifier> enum_fields;
|
||||
for (auto &variant_record : variant_records)
|
||||
{
|
||||
TyTy::VariantDef *variant = type.get_variants ().at (i++);
|
||||
std::string implicit_variant_name = variant->get_identifier ();
|
||||
|
||||
Backend::typed_identifier f (implicit_variant_name, variant_record,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
type.get_ty_ref ()));
|
||||
enum_fields.push_back (std::move (f));
|
||||
}
|
||||
|
||||
// finally make the union or the enum
|
||||
type_record = ctx->get_backend ()->union_type (enum_fields);
|
||||
}
|
||||
|
||||
// Handle repr options
|
||||
// TODO: "packed" should only narrow type alignment and "align" should only
|
||||
// widen it. Do we need to check and enforce this here, or is it taken care of
|
||||
// later on in the gcc middle-end?
|
||||
TyTy::ADTType::ReprOptions repr = type.get_repr_options ();
|
||||
if (repr.pack)
|
||||
{
|
||||
TYPE_PACKED (type_record) = 1;
|
||||
if (repr.pack > 1)
|
||||
{
|
||||
SET_TYPE_ALIGN (type_record, repr.pack * 8);
|
||||
TYPE_USER_ALIGN (type_record) = 1;
|
||||
}
|
||||
}
|
||||
else if (repr.align)
|
||||
{
|
||||
SET_TYPE_ALIGN (type_record, repr.align * 8);
|
||||
TYPE_USER_ALIGN (type_record) = 1;
|
||||
}
|
||||
|
||||
std::string named_struct_str
|
||||
= type.get_ident ().path.get () + type.subst_as_string ();
|
||||
translated = ctx->get_backend ()->named_type (named_struct_str, type_record,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::TupleType &type)
|
||||
{
|
||||
if (type.num_fields () == 0)
|
||||
{
|
||||
translated = ctx->get_backend ()->unit_type ();
|
||||
return;
|
||||
}
|
||||
|
||||
// create implicit struct
|
||||
std::vector<Backend::typed_identifier> fields;
|
||||
for (size_t i = 0; i < type.num_fields (); i++)
|
||||
{
|
||||
TyTy::BaseType *field = type.get_field (i);
|
||||
tree compiled_field_ty = TyTyResolveCompile::compile (ctx, field);
|
||||
|
||||
// rustc uses the convention __N, where N is an integer, to
|
||||
// name the fields of a tuple. We follow this as well,
|
||||
// because this is used by GDB. One further reason to prefer
|
||||
// this, rather than simply emitting the integer, is that this
|
||||
// approach makes it simpler to use a C-only debugger, or
|
||||
// GDB's C mode, when debugging Rust.
|
||||
Backend::typed_identifier f ("__" + std::to_string (i), compiled_field_ty,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
type.get_ty_ref ()));
|
||||
fields.push_back (std::move (f));
|
||||
}
|
||||
|
||||
tree struct_type_record = ctx->get_backend ()->struct_type (fields);
|
||||
translated
|
||||
= ctx->get_backend ()->named_type (type.as_string (), struct_type_record,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ArrayType &type)
|
||||
{
|
||||
tree element_type
|
||||
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
|
||||
tree capacity_expr = CompileExpr::Compile (&type.get_capacity_expr (), ctx);
|
||||
tree folded_capacity_expr = fold_expr (capacity_expr);
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->array_type (element_type, folded_capacity_expr);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::SliceType &type)
|
||||
{
|
||||
tree type_record = create_slice_type_record (type);
|
||||
|
||||
std::string named_struct_str
|
||||
= std::string ("[") + type.get_element_type ()->get_name () + "]";
|
||||
translated = ctx->get_backend ()->named_type (named_struct_str, type_record,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::BoolType &type)
|
||||
{
|
||||
translated
|
||||
= ctx->get_backend ()->named_type ("bool",
|
||||
ctx->get_backend ()->bool_type (),
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::IntType &type)
|
||||
{
|
||||
switch (type.get_int_kind ())
|
||||
{
|
||||
case TyTy::IntType::I8:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"i8", ctx->get_backend ()->integer_type (false, 8),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::IntType::I16:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"i16", ctx->get_backend ()->integer_type (false, 16),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::IntType::I32:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"i32", ctx->get_backend ()->integer_type (false, 32),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::IntType::I64:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"i64", ctx->get_backend ()->integer_type (false, 64),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::IntType::I128:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"i128", ctx->get_backend ()->integer_type (false, 128),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::UintType &type)
|
||||
{
|
||||
switch (type.get_uint_kind ())
|
||||
{
|
||||
case TyTy::UintType::U8:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"u8", ctx->get_backend ()->integer_type (true, 8),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::UintType::U16:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"u16", ctx->get_backend ()->integer_type (true, 16),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::UintType::U32:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"u32", ctx->get_backend ()->integer_type (true, 32),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::UintType::U64:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"u64", ctx->get_backend ()->integer_type (true, 64),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::UintType::U128:
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"u128", ctx->get_backend ()->integer_type (true, 128),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::FloatType &type)
|
||||
{
|
||||
switch (type.get_float_kind ())
|
||||
{
|
||||
case TyTy::FloatType::F32:
|
||||
translated
|
||||
= ctx->get_backend ()->named_type ("f32",
|
||||
ctx->get_backend ()->float_type (32),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
|
||||
case TyTy::FloatType::F64:
|
||||
translated
|
||||
= ctx->get_backend ()->named_type ("f64",
|
||||
ctx->get_backend ()->float_type (64),
|
||||
Linemap::predeclared_location ());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::USizeType &type)
|
||||
{
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"usize",
|
||||
ctx->get_backend ()->integer_type (
|
||||
true, ctx->get_backend ()->get_pointer_size ()),
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ISizeType &type)
|
||||
{
|
||||
translated = ctx->get_backend ()->named_type (
|
||||
"isize",
|
||||
ctx->get_backend ()->integer_type (
|
||||
false, ctx->get_backend ()->get_pointer_size ()),
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::CharType &type)
|
||||
{
|
||||
translated
|
||||
= ctx->get_backend ()->named_type ("char",
|
||||
ctx->get_backend ()->wchar_type (),
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::ReferenceType &type)
|
||||
{
|
||||
const TyTy::SliceType *slice = nullptr;
|
||||
const TyTy::StrType *str = nullptr;
|
||||
if (type.is_dyn_slice_type (&slice))
|
||||
{
|
||||
tree type_record = create_slice_type_record (*slice);
|
||||
std::string dyn_slice_type_str
|
||||
= std::string (type.is_mutable () ? "&mut " : "&") + "["
|
||||
+ slice->get_element_type ()->get_name () + "]";
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->named_type (dyn_slice_type_str, type_record,
|
||||
slice->get_locus ());
|
||||
|
||||
return;
|
||||
}
|
||||
else if (type.is_dyn_str_type (&str))
|
||||
{
|
||||
tree type_record = create_str_type_record (*str);
|
||||
std::string dyn_str_type_str
|
||||
= std::string (type.is_mutable () ? "&mut " : "&") + "str";
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->named_type (dyn_str_type_str, type_record,
|
||||
str->get_locus ());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tree base_compiled_type
|
||||
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
|
||||
if (type.is_mutable ())
|
||||
{
|
||||
translated = ctx->get_backend ()->reference_type (base_compiled_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto base = ctx->get_backend ()->immutable_type (base_compiled_type);
|
||||
translated = ctx->get_backend ()->reference_type (base);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::PointerType &type)
|
||||
{
|
||||
const TyTy::SliceType *slice = nullptr;
|
||||
const TyTy::StrType *str = nullptr;
|
||||
if (type.is_dyn_slice_type (&slice))
|
||||
{
|
||||
tree type_record = create_slice_type_record (*slice);
|
||||
std::string dyn_slice_type_str
|
||||
= std::string (type.is_mutable () ? "*mut " : "*const ") + "["
|
||||
+ slice->get_element_type ()->get_name () + "]";
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->named_type (dyn_slice_type_str, type_record,
|
||||
slice->get_locus ());
|
||||
|
||||
return;
|
||||
}
|
||||
else if (type.is_dyn_str_type (&str))
|
||||
{
|
||||
tree type_record = create_str_type_record (*str);
|
||||
std::string dyn_str_type_str
|
||||
= std::string (type.is_mutable () ? "*mut " : "*const ") + "str";
|
||||
|
||||
translated
|
||||
= ctx->get_backend ()->named_type (dyn_str_type_str, type_record,
|
||||
str->get_locus ());
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tree base_compiled_type
|
||||
= TyTyResolveCompile::compile (ctx, type.get_base (), trait_object_mode);
|
||||
if (type.is_mutable ())
|
||||
{
|
||||
translated = ctx->get_backend ()->pointer_type (base_compiled_type);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto base = ctx->get_backend ()->immutable_type (base_compiled_type);
|
||||
translated = ctx->get_backend ()->pointer_type (base);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::StrType &type)
|
||||
{
|
||||
tree raw_str = create_str_type_record (type);
|
||||
translated
|
||||
= ctx->get_backend ()->named_type ("str", raw_str,
|
||||
Linemap::predeclared_location ());
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::NeverType &)
|
||||
{
|
||||
translated = ctx->get_backend ()->unit_type ();
|
||||
}
|
||||
|
||||
void
|
||||
TyTyResolveCompile::visit (const TyTy::DynamicObjectType &type)
|
||||
{
|
||||
if (trait_object_mode)
|
||||
{
|
||||
translated = ctx->get_backend ()->integer_type (
|
||||
true, ctx->get_backend ()->get_pointer_size ());
|
||||
return;
|
||||
}
|
||||
|
||||
// create implicit struct
|
||||
auto items = type.get_object_items ();
|
||||
std::vector<Backend::typed_identifier> fields;
|
||||
|
||||
tree uint = ctx->get_backend ()->integer_type (
|
||||
true, ctx->get_backend ()->get_pointer_size ());
|
||||
tree uintptr_ty = build_pointer_type (uint);
|
||||
|
||||
Backend::typed_identifier f ("pointer", uintptr_ty,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
type.get_ty_ref ()));
|
||||
fields.push_back (std::move (f));
|
||||
|
||||
tree vtable_size = build_int_cst (size_type_node, items.size ());
|
||||
tree vtable_type = ctx->get_backend ()->array_type (uintptr_ty, vtable_size);
|
||||
Backend::typed_identifier vtf ("vtable", vtable_type,
|
||||
ctx->get_mappings ()->lookup_location (
|
||||
type.get_ty_ref ()));
|
||||
fields.push_back (std::move (vtf));
|
||||
|
||||
tree type_record = ctx->get_backend ()->struct_type (fields);
|
||||
translated = ctx->get_backend ()->named_type (type.get_name (), type_record,
|
||||
type.get_ident ().locus);
|
||||
}
|
||||
|
||||
tree
|
||||
TyTyResolveCompile::create_slice_type_record (const TyTy::SliceType &type)
|
||||
{
|
||||
// lookup usize
|
||||
TyTy::BaseType *usize = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
|
||||
rust_assert (ok);
|
||||
|
||||
tree element_type
|
||||
= TyTyResolveCompile::compile (ctx, type.get_element_type ());
|
||||
tree data_field_ty = build_pointer_type (element_type);
|
||||
Backend::typed_identifier data_field ("data", data_field_ty,
|
||||
type.get_locus ());
|
||||
|
||||
tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
|
||||
Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
|
||||
|
||||
tree record = ctx->get_backend ()->struct_type ({data_field, len_field});
|
||||
SLICE_FLAG (record) = 1;
|
||||
TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
tree
|
||||
TyTyResolveCompile::create_str_type_record (const TyTy::StrType &type)
|
||||
{
|
||||
// lookup usize
|
||||
TyTy::BaseType *usize = nullptr;
|
||||
bool ok = ctx->get_tyctx ()->lookup_builtin ("usize", &usize);
|
||||
rust_assert (ok);
|
||||
|
||||
tree char_ptr = build_pointer_type (char_type_node);
|
||||
tree const_char_type = build_qualified_type (char_ptr, TYPE_QUAL_CONST);
|
||||
|
||||
tree element_type = const_char_type;
|
||||
tree data_field_ty = build_pointer_type (element_type);
|
||||
Backend::typed_identifier data_field ("data", data_field_ty,
|
||||
type.get_locus ());
|
||||
|
||||
tree len_field_ty = TyTyResolveCompile::compile (ctx, usize);
|
||||
Backend::typed_identifier len_field ("len", len_field_ty, type.get_locus ());
|
||||
|
||||
tree record = ctx->get_backend ()->struct_type ({data_field, len_field});
|
||||
SLICE_FLAG (record) = 1;
|
||||
TYPE_MAIN_VARIANT (record) = ctx->insert_main_variant (record);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
79
gcc/rust/backend/rust-compile-type.h
Normal file
79
gcc/rust/backend/rust-compile-type.h
Normal file
@@ -0,0 +1,79 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_TYPE
|
||||
#define RUST_COMPILE_TYPE
|
||||
|
||||
#include "rust-compile-context.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class TyTyResolveCompile : protected TyTy::TyConstVisitor
|
||||
{
|
||||
public:
|
||||
static tree compile (Context *ctx, const TyTy::BaseType *ty,
|
||||
bool trait_object_mode = false);
|
||||
|
||||
static tree get_implicit_enumeral_node_type (Context *ctx);
|
||||
|
||||
void visit (const TyTy::InferType &) override;
|
||||
void visit (const TyTy::ADTType &) override;
|
||||
void visit (const TyTy::TupleType &) override;
|
||||
void visit (const TyTy::FnType &) override;
|
||||
void visit (const TyTy::FnPtr &) override;
|
||||
void visit (const TyTy::ArrayType &) override;
|
||||
void visit (const TyTy::SliceType &) override;
|
||||
void visit (const TyTy::BoolType &) override;
|
||||
void visit (const TyTy::IntType &) override;
|
||||
void visit (const TyTy::UintType &) override;
|
||||
void visit (const TyTy::FloatType &) override;
|
||||
void visit (const TyTy::USizeType &) override;
|
||||
void visit (const TyTy::ISizeType &) override;
|
||||
void visit (const TyTy::ErrorType &) override;
|
||||
void visit (const TyTy::CharType &) override;
|
||||
void visit (const TyTy::ReferenceType &) override;
|
||||
void visit (const TyTy::PointerType &) override;
|
||||
void visit (const TyTy::ParamType &) override;
|
||||
void visit (const TyTy::StrType &) override;
|
||||
void visit (const TyTy::NeverType &) override;
|
||||
void visit (const TyTy::PlaceholderType &) override;
|
||||
void visit (const TyTy::ProjectionType &) override;
|
||||
void visit (const TyTy::DynamicObjectType &) override;
|
||||
void visit (const TyTy::ClosureType &) override;
|
||||
|
||||
public:
|
||||
static hashval_t type_hasher (tree type);
|
||||
|
||||
protected:
|
||||
tree create_slice_type_record (const TyTy::SliceType &type);
|
||||
tree create_str_type_record (const TyTy::StrType &type);
|
||||
|
||||
private:
|
||||
TyTyResolveCompile (Context *ctx, bool trait_object_mode);
|
||||
|
||||
Context *ctx;
|
||||
bool trait_object_mode;
|
||||
tree translated;
|
||||
int recurisve_ops;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_TYPE
|
||||
95
gcc/rust/backend/rust-compile-var-decl.h
Normal file
95
gcc/rust/backend/rust-compile-var-decl.h
Normal file
@@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2020-2022 Free Software Foundation, Inc.
|
||||
|
||||
// This file is part of GCC.
|
||||
|
||||
// GCC is free software; you can redistribute it and/or modify it under
|
||||
// the terms of the GNU General Public License as published by the Free
|
||||
// Software Foundation; either version 3, or (at your option) any later
|
||||
// version.
|
||||
|
||||
// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
// for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with GCC; see the file COPYING3. If not see
|
||||
// <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef RUST_COMPILE_VAR_DECL
|
||||
#define RUST_COMPILE_VAR_DECL
|
||||
|
||||
#include "rust-compile-base.h"
|
||||
#include "rust-hir-visitor.h"
|
||||
|
||||
namespace Rust {
|
||||
namespace Compile {
|
||||
|
||||
class CompileVarDecl : public HIRCompileBase, public HIR::HIRPatternVisitor
|
||||
{
|
||||
using HIR::HIRPatternVisitor::visit;
|
||||
|
||||
public:
|
||||
static ::Bvariable *compile (tree fndecl, tree translated_type,
|
||||
HIR::Pattern *pattern, Context *ctx)
|
||||
{
|
||||
CompileVarDecl compiler (ctx, fndecl, translated_type);
|
||||
pattern->accept_vis (compiler);
|
||||
return compiler.compiled_variable;
|
||||
}
|
||||
|
||||
void visit (HIR::IdentifierPattern &pattern) override
|
||||
{
|
||||
if (!pattern.is_mut ())
|
||||
translated_type = ctx->get_backend ()->immutable_type (translated_type);
|
||||
|
||||
compiled_variable
|
||||
= ctx->get_backend ()->local_variable (fndecl, pattern.get_identifier (),
|
||||
translated_type, NULL /*decl_var*/,
|
||||
pattern.get_locus ());
|
||||
|
||||
HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
|
||||
ctx->insert_var_decl (stmt_id, compiled_variable);
|
||||
}
|
||||
|
||||
void visit (HIR::WildcardPattern &pattern) override
|
||||
{
|
||||
translated_type = ctx->get_backend ()->immutable_type (translated_type);
|
||||
|
||||
compiled_variable
|
||||
= ctx->get_backend ()->local_variable (fndecl, "_", translated_type,
|
||||
NULL /*decl_var*/,
|
||||
pattern.get_locus ());
|
||||
|
||||
HirId stmt_id = pattern.get_pattern_mappings ().get_hirid ();
|
||||
ctx->insert_var_decl (stmt_id, compiled_variable);
|
||||
}
|
||||
|
||||
// Empty visit for unused Pattern HIR nodes.
|
||||
void visit (HIR::GroupedPattern &) override {}
|
||||
void visit (HIR::LiteralPattern &) override {}
|
||||
void visit (HIR::PathInExpression &) override {}
|
||||
void visit (HIR::QualifiedPathInExpression &) override {}
|
||||
void visit (HIR::RangePattern &) override {}
|
||||
void visit (HIR::ReferencePattern &) override {}
|
||||
void visit (HIR::SlicePattern &) override {}
|
||||
void visit (HIR::StructPattern &) override {}
|
||||
void visit (HIR::TuplePattern &) override {}
|
||||
void visit (HIR::TupleStructPattern &) override {}
|
||||
|
||||
private:
|
||||
CompileVarDecl (Context *ctx, tree fndecl, tree translated_type)
|
||||
: HIRCompileBase (ctx), fndecl (fndecl), translated_type (translated_type),
|
||||
compiled_variable (ctx->get_backend ()->error_variable ())
|
||||
{}
|
||||
|
||||
tree fndecl;
|
||||
tree translated_type;
|
||||
|
||||
Bvariable *compiled_variable;
|
||||
};
|
||||
|
||||
} // namespace Compile
|
||||
} // namespace Rust
|
||||
|
||||
#endif // RUST_COMPILE_VAR_DECL
|
||||
Reference in New Issue
Block a user