// Copyright (C) 2020 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
// .
#ifndef RUST_COMPILE_CONTEXT
#define RUST_COMPILE_CONTEXT
#include "rust-system.h"
#include "rust-hir-map.h"
#include "rust-name-resolver.h"
#include "rust-hir-type-check.h"
#include "rust-backend.h"
#include "rust-compile-tyty.h"
#include "rust-ast-full.h"
namespace Rust {
namespace Compile {
struct fncontext
{
::Bfunction *fndecl;
::Bvariable *ret_addr;
};
class Context
{
public:
Context (::Backend *backend)
: backend (backend), resolver (Resolver::Resolver::get ()),
tyctx (Resolver::TypeCheckContext::get ()),
mappings (Analysis::Mappings::get ())
{
// insert the builtins
auto builtins = resolver->get_builtin_types ();
for (auto it = builtins.begin (); it != builtins.end (); it++)
{
HirId ref;
rust_assert (
tyctx->lookup_type_by_node_id ((*it)->get_node_id (), &ref));
TyTy::TyBase *lookup;
rust_assert (tyctx->lookup_type (ref, &lookup));
auto compiled = TyTyCompile::compile (backend, lookup);
compiled_type_map[ref] = compiled;
}
}
~Context () {}
bool lookup_compiled_types (HirId id, ::Btype **type)
{
auto it = compiled_type_map.find (id);
if (it == compiled_type_map.end ())
return false;
*type = it->second;
return true;
}
void insert_compiled_type (HirId id, ::Btype *type)
{
compiled_type_map[id] = type;
}
::Backend *get_backend () { return backend; }
Resolver::Resolver *get_resolver () { return resolver; }
Resolver::TypeCheckContext *get_tyctx () { return tyctx; }
Analysis::Mappings *get_mappings () { return mappings; }
void push_block (Bblock *scope)
{
scope_stack.push_back (scope);
statements.push_back ({});
}
Bblock *pop_block ()
{
auto block = scope_stack.back ();
scope_stack.pop_back ();
auto stmts = statements.back ();
statements.pop_back ();
backend->block_add_statements (block, stmts);
return block;
}
Bblock *peek_enclosing_scope ()
{
if (scope_stack.size () == 0)
return nullptr;
return scope_stack.back ();
}
void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); }
void insert_var_decl (HirId id, ::Bvariable *decl)
{
compiled_var_decls[id] = decl;
}
bool lookup_var_decl (HirId id, ::Bvariable **decl)
{
auto it = compiled_var_decls.find (id);
if (it == compiled_var_decls.end ())
return false;
*decl = it->second;
return true;
}
void insert_function_decl (HirId id, ::Bfunction *fn)
{
compiled_fn_map[id] = fn;
}
bool lookup_function_decl (HirId id, ::Bfunction **fn)
{
auto it = compiled_fn_map.find (id);
if (it == compiled_fn_map.end ())
return false;
*fn = it->second;
return true;
}
void push_fn (::Bfunction *fn, ::Bvariable *ret_addr)
{
fn_stack.push_back (fncontext{fn, ret_addr});
}
void pop_fn () { fn_stack.pop_back (); }
fncontext peek_fn () { return fn_stack.back (); }
void push_type (::Btype *t) { type_decls.push_back (t); }
void push_var (::Bvariable *v) { var_decls.push_back (v); }
void push_const (::Bexpression *c) { const_decls.push_back (c); }
void push_function (::Bfunction *f) { func_decls.push_back (f); }
void write_to_backend ()
{
backend->write_global_definitions (type_decls, const_decls, func_decls,
var_decls);
}
bool function_completed (Bfunction *fn)
{
for (auto it = func_decls.begin (); it != func_decls.end (); it++)
{
Bfunction *i = (*it);
if (i == fn)
{
return true;
}
}
return false;
}
private:
::Backend *backend;
Resolver::Resolver *resolver;
Resolver::TypeCheckContext *tyctx;
Analysis::Mappings *mappings;
// state
std::vector fn_stack;
std::map compiled_var_decls;
std::map compiled_type_map;
std::map compiled_fn_map;
std::vector< ::std::vector > statements;
std::vector< ::Bblock *> scope_stack;
// To GCC middle-end
std::vector< ::Btype *> type_decls;
std::vector< ::Bvariable *> var_decls;
std::vector< ::Bexpression *> const_decls;
std::vector< ::Bfunction *> func_decls;
};
class TyTyResolveCompile : public TyTy::TyVisitor
{
public:
static ::Btype *compile (Context *ctx, TyTy::TyBase *ty)
{
TyTyResolveCompile compiler (ctx);
ty->accept_vis (compiler);
return compiler.translated;
}
virtual ~TyTyResolveCompile () {}
void visit (TyTy::UnitType &type) override { gcc_unreachable (); }
void visit (TyTy::InferType &type) override { gcc_unreachable (); }
void visit (TyTy::FnType &type) override { gcc_unreachable (); }
void visit (TyTy::BoolType &type) override
{
::Btype *compiled_type = nullptr;
bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
void visit (TyTy::IntType &type) override
{
printf ("type [%s] has ref: %u\n", type.as_string ().c_str (),
type.get_ref ());
::Btype *compiled_type = nullptr;
bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
void visit (TyTy::UintType &type) override
{
::Btype *compiled_type = nullptr;
bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type);
rust_assert (ok);
translated = compiled_type;
}
private:
TyTyResolveCompile (Context *ctx) : ctx (ctx) {}
Context *ctx;
::Btype *translated;
};
} // namespace Compile
} // namespace Rust
#endif // RUST_COMPILE_CONTEXT