xref: /netbsd-src/external/gpl3/gcc/dist/gcc/d/d-compiler.cc (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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 *
paintAsType(UnionExp *,Expression * expr,Type * type)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
onParseModule(Module * m)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
onImport(Module *)154 Compiler::onImport (Module *)
155 {
156   return false;
157 }
158