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