Home | History | Annotate | Line # | Download | only in d
d-compiler.cc revision 1.1
      1 /* d-compiler.cc -- D frontend interface to the gcc back-end.
      2    Copyright (C) 2020-2022 Free Software Foundation, Inc.
      3 
      4 GCC is free software; you can redistribute it and/or modify
      5 it under the terms of the GNU General Public License as published by
      6 the Free Software Foundation; either version 3, or (at your option)
      7 any later version.
      8 
      9 GCC is distributed in the hope that it will be useful,
     10 but WITHOUT ANY WARRANTY; without even the implied warranty of
     11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     12 GNU General Public License for more details.
     13 
     14 You should have received a copy of the GNU General Public License
     15 along with GCC; see the file COPYING3.  If not see
     16 <http://www.gnu.org/licenses/>.  */
     17 
     18 #include "config.h"
     19 #include "system.h"
     20 #include "coretypes.h"
     21 
     22 #include "dmd/compiler.h"
     23 #include "dmd/expression.h"
     24 #include "dmd/identifier.h"
     25 #include "dmd/module.h"
     26 #include "dmd/mtype.h"
     27 
     28 #include "tree.h"
     29 #include "fold-const.h"
     30 
     31 #include "d-tree.h"
     32 
     33 
     34 /* Implements the Compiler interface used by the frontend.  */
     35 
     36 /* Perform a reinterpret cast of EXPR to type TYPE for use in CTFE.
     37    The front end should have already ensured that EXPR is a constant,
     38    so we just lower the value to GCC and return the converted CST.  */
     39 
     40 Expression *
     41 Compiler::paintAsType (UnionExp *, Expression *expr, Type *type)
     42 {
     43   /* We support up to 512-bit values.  */
     44   unsigned char buffer[64];
     45   tree cst;
     46 
     47   Type *tb = type->toBasetype ();
     48 
     49   if (expr->type->isintegral ())
     50     cst = build_integer_cst (expr->toInteger (), build_ctype (expr->type));
     51   else if (expr->type->isfloating ())
     52     cst = build_float_cst (expr->toReal (), expr->type);
     53   else if (expr->op == EXP::arrayLiteral)
     54     {
     55       /* Build array as VECTOR_CST, assumes EXPR is constant.  */
     56       Expressions *elements = expr->isArrayLiteralExp ()->elements;
     57       vec <constructor_elt, va_gc> *elms = NULL;
     58 
     59       vec_safe_reserve (elms, elements->length);
     60       for (size_t i = 0; i < elements->length; i++)
     61 	{
     62 	  Expression *e = (*elements)[i];
     63 	  if (e->type->isintegral ())
     64 	    {
     65 	      tree value = build_integer_cst (e->toInteger (),
     66 					      build_ctype (e->type));
     67 	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
     68 	    }
     69 	  else if (e->type->isfloating ())
     70 	    {
     71 	      tree value = build_float_cst (e->toReal (), e->type);
     72 	      CONSTRUCTOR_APPEND_ELT (elms, size_int (i), value);
     73 	    }
     74 	  else
     75 	    gcc_unreachable ();
     76 	}
     77 
     78       /* Build vector type.  */
     79       int nunits = expr->type->isTypeSArray ()->dim->toUInteger ();
     80       Type *telem = expr->type->nextOf ();
     81       tree vectype = build_vector_type (build_ctype (telem), nunits);
     82 
     83       cst = build_vector_from_ctor (vectype, elms);
     84     }
     85   else
     86     gcc_unreachable ();
     87 
     88   /* Encode CST to buffer.  */
     89   int len = native_encode_expr (cst, buffer, sizeof (buffer));
     90 
     91   if (tb->ty == TY::Tsarray)
     92     {
     93       /* Interpret value as a vector of the same size,
     94 	 then return the array literal.  */
     95       int nunits = type->isTypeSArray ()->dim->toUInteger ();
     96       Type *elem = type->nextOf ();
     97       tree vectype = build_vector_type (build_ctype (elem), nunits);
     98 
     99       cst = native_interpret_expr (vectype, buffer, len);
    100 
    101       Expression *e = d_eval_constant_expression (expr->loc, cst);
    102       gcc_assert (e != NULL && e->op == EXP::vector);
    103 
    104       return e->isVectorExp ()->e1;
    105     }
    106   else
    107     {
    108       /* Normal interpret cast.  */
    109       cst = native_interpret_expr (build_ctype (type), buffer, len);
    110 
    111       Expression *e = d_eval_constant_expression (expr->loc, cst);
    112       gcc_assert (e != NULL);
    113 
    114       return e;
    115     }
    116 }
    117 
    118 /* Check imported module M for any special processing.
    119    Modules we look out for are:
    120     - object: For D runtime type information.
    121     - gcc.builtins: For all gcc builtins.
    122     - core.stdc.*: For all gcc library builtins.  */
    123 
    124 void
    125 Compiler::onParseModule (Module *m)
    126 {
    127   ModuleDeclaration *md = m->md;
    128 
    129   if (!md || !md->id|| md->packages.length == 0)
    130     {
    131       Identifier *id = (md && md->id) ? md->id : m->ident;
    132       if (!strcmp (id->toChars (), "object"))
    133 	create_tinfo_types (m);
    134     }
    135   else if (md->packages.length == 1)
    136     {
    137       if (!strcmp (md->packages.ptr[0]->toChars (), "gcc")
    138 	  && !strcmp (md->id->toChars (), "builtins"))
    139 	d_build_builtins_module (m);
    140     }
    141   else if (md->packages.length == 2)
    142     {
    143       if (!strcmp (md->packages.ptr[0]->toChars (), "core")
    144 	  && !strcmp (md->packages.ptr[1]->toChars (), "stdc"))
    145 	d_add_builtin_module (m);
    146     }
    147 }
    148 
    149 /* A callback function that is called once an imported module is parsed.
    150    If the callback returns true, then it tells the front-end that the
    151    driver intends on compiling the import.  */
    152 
    153 bool
    154 Compiler::onImport (Module *)
    155 {
    156   return false;
    157 }
    158