1 // Compiler implementation of the D programming language 2 // Copyright (c) 1999-2015 by Digital Mars 3 // All Rights Reserved 4 // written by Walter Bright 5 // http://www.digitalmars.com 6 // Distributed under the Boost Software License, Version 1.0. 7 // http://www.boost.org/LICENSE_1_0.txt 8 9 module ddmd.globals; 10 11 import core.stdc.stdint; 12 import core.stdc.stdio; 13 import core.stdc.string; 14 import ddmd.root.array; 15 import ddmd.root.filename; 16 import ddmd.root.outbuffer; 17 18 template xversion(string s) 19 { 20 enum xversion = mixin(`{ version (` ~ s ~ `) return true; else return false; }`)(); 21 } 22 23 private string stripRight(string s) 24 { 25 while (s.length && (s[$ - 1] == ' ' || s[$ - 1] == '\n' || s[$ - 1] == '\r')) 26 s = s[0 .. $ - 1]; 27 return s; 28 } 29 30 enum __linux__ = xversion!`linux`; 31 enum __APPLE__ = xversion!`OSX`; 32 enum __FreeBSD__ = xversion!`FreeBSD`; 33 enum __OpenBSD__ = xversion!`OpenBSD`; 34 enum __sun = xversion!`Solaris`; 35 36 enum IN_GCC = xversion!`IN_GCC`; 37 38 enum TARGET_LINUX = xversion!`linux`; 39 enum TARGET_OSX = xversion!`OSX`; 40 enum TARGET_FREEBSD = xversion!`FreeBSD`; 41 enum TARGET_OPENBSD = xversion!`OpenBSD`; 42 enum TARGET_SOLARIS = xversion!`Solaris`; 43 enum TARGET_WINDOS = xversion!`Windows`; 44 45 enum BOUNDSCHECK : int 46 { 47 BOUNDSCHECKdefault, // initial value 48 BOUNDSCHECKoff, // never do bounds checking 49 BOUNDSCHECKon, // always do bounds checking 50 BOUNDSCHECKsafeonly, // do bounds checking only in @safe functions 51 } 52 53 alias BOUNDSCHECKdefault = BOUNDSCHECK.BOUNDSCHECKdefault; 54 alias BOUNDSCHECKoff = BOUNDSCHECK.BOUNDSCHECKoff; 55 alias BOUNDSCHECKon = BOUNDSCHECK.BOUNDSCHECKon; 56 alias BOUNDSCHECKsafeonly = BOUNDSCHECK.BOUNDSCHECKsafeonly; 57 58 // Put command line switches in here 59 struct Param 60 { 61 bool obj; // write object file 62 bool link; // perform link 63 bool dll; // generate shared dynamic library 64 bool lib; // write library file instead of object file(s) 65 bool multiobj; // break one object file into multiple ones 66 bool oneobj; // write one object file instead of multiple ones 67 bool trace; // insert profiling hooks 68 bool tracegc; // instrument calls to 'new' 69 bool verbose; // verbose compile 70 bool showColumns; // print character (column) numbers in diagnostics 71 bool vtls; // identify thread local variables 72 bool vgc; // identify gc usage 73 bool vfield; // identify non-mutable field variables 74 bool vcomplex; // identify complex/imaginary type usage 75 ubyte symdebug; // insert debug symbolic information 76 bool alwaysframe; // always emit standard stack frame 77 bool optimize; // run optimizer 78 bool map; // generate linker .map file 79 bool is64bit; // generate 64 bit code 80 bool isLP64; // generate code for LP64 81 bool isLinux; // generate code for linux 82 bool isOSX; // generate code for Mac OSX 83 bool isWindows; // generate code for Windows 84 bool isFreeBSD; // generate code for FreeBSD 85 bool isOpenBSD; // generate code for OpenBSD 86 bool isSolaris; // generate code for Solaris 87 bool mscoff; // for Win32: write COFF object files instead of OMF 88 // 0: don't allow use of deprecated features 89 // 1: silently allow use of deprecated features 90 // 2: warn about the use of deprecated features 91 byte useDeprecated; 92 bool useAssert; // generate runtime code for assert()'s 93 bool useInvariants; // generate class invariant checks 94 bool useIn; // generate precondition checks 95 bool useOut; // generate postcondition checks 96 bool stackstomp; // add stack stomping code 97 bool useSwitchError; // check for switches without a default 98 bool useUnitTests; // generate unittest code 99 bool useInline; // inline expand functions 100 bool useDIP25; // implement http://wiki.dlang.org/DIP25 101 bool release; // build release version 102 bool preservePaths; // true means don't strip path from source file 103 // 0: disable warnings 104 // 1: warnings as errors 105 // 2: informational warnings (no errors) 106 byte warnings; 107 bool pic; // generate position-independent-code for shared libs 108 bool color; // use ANSI colors in console output 109 bool cov; // generate code coverage data 110 ubyte covPercent; // 0..100 code coverage percentage required 111 bool nofloat; // code should not pull in floating point support 112 bool ignoreUnsupportedPragmas; // rather than error on them 113 bool enforcePropertySyntax; 114 bool betterC; // be a "better C" compiler; no dependency on D runtime 115 bool addMain; // add a default main() function 116 bool allInst; // generate code for all template instantiations 117 bool dwarfeh; // generate dwarf eh exception handling 118 bool check10378; // check for issues transitioning to 10738 119 bool bug10378; // use pre-bugzilla 10378 search strategy 120 121 BOUNDSCHECK useArrayBounds; 122 123 const(char)* argv0; // program name 124 Array!(const(char)*)* imppath; // array of char*'s of where to look for import modules 125 Array!(const(char)*)* fileImppath; // array of char*'s of where to look for file import modules 126 const(char)* objdir; // .obj/.lib file output directory 127 const(char)* objname; // .obj file output name 128 const(char)* libname; // .lib file output name 129 130 bool doDocComments; // process embedded documentation comments 131 const(char)* docdir; // write documentation file to docdir directory 132 const(char)* docname; // write documentation file to docname 133 Array!(const(char)*)* ddocfiles; // macro include files for Ddoc 134 135 bool doHdrGeneration; // process embedded documentation comments 136 const(char)* hdrdir; // write 'header' file to docdir directory 137 const(char)* hdrname; // write 'header' file to docname 138 139 bool doJsonGeneration; // write JSON file 140 const(char)* jsonfilename; // write JSON file to jsonfilename 141 142 uint debuglevel; // debug level 143 Array!(const(char)*)* debugids; // debug identifiers 144 145 uint versionlevel; // version level 146 Array!(const(char)*)* versionids; // version identifiers 147 148 const(char)* defaultlibname; // default library for non-debug builds 149 const(char)* debuglibname; // default library for debug builds 150 151 const(char)* moduleDepsFile; // filename for deps output 152 OutBuffer* moduleDeps; // contents to be written to deps file 153 154 // Hidden debug switches 155 bool debugb; 156 bool debugc; 157 bool debugf; 158 bool debugr; 159 bool debugx; 160 bool debugy; 161 162 bool run; // run resulting executable 163 Strings runargs; // arguments for executable 164 165 // Linker stuff 166 Array!(const(char)*)* objfiles; 167 Array!(const(char)*)* linkswitches; 168 Array!(const(char)*)* libfiles; 169 Array!(const(char)*)* dllfiles; 170 const(char)* deffile; 171 const(char)* resfile; 172 const(char)* exefile; 173 const(char)* mapfile; 174 } 175 176 struct Compiler 177 { 178 const(char)* vendor; // Compiler backend name 179 } 180 181 alias structalign_t = uint; 182 183 // magic value means "match whatever the underlying C compiler does" 184 // other values are all powers of 2 185 enum STRUCTALIGN_DEFAULT = (cast(structalign_t)~0); 186 187 struct Global 188 { 189 const(char)* inifilename; 190 const(char)* mars_ext; 191 const(char)* obj_ext; 192 const(char)* lib_ext; 193 const(char)* dll_ext; 194 const(char)* doc_ext; // for Ddoc generated files 195 const(char)* ddoc_ext; // for Ddoc macro include files 196 const(char)* hdr_ext; // for D 'header' import files 197 const(char)* json_ext; // for JSON files 198 const(char)* map_ext; // for .map files 199 bool run_noext; // allow -run sources without extensions. 200 201 const(char)* copyright; 202 const(char)* written; 203 const(char)* main_d; // dummy filename for dummy main() 204 Array!(const(char)*)* path; // Array of char*'s which form the import lookup path 205 Array!(const(char)*)* filePath; // Array of char*'s which form the file import lookup path 206 207 const(char)* _version; 208 209 Compiler compiler; 210 Param params; 211 uint errors; // number of errors reported so far 212 uint warnings; // number of warnings reported so far 213 FILE* stdmsg; // where to send verbose messages 214 uint gag; // !=0 means gag reporting of errors & warnings 215 uint gaggedErrors; // number of errors reported while gagged 216 217 uint errorLimit; 218 219 /* Start gagging. Return the current number of gagged errors 220 */ 221 extern (C++) uint startGagging() 222 { 223 ++gag; 224 return gaggedErrors; 225 } 226 227 /* End gagging, restoring the old gagged state. 228 * Return true if errors occured while gagged. 229 */ 230 extern (C++) bool endGagging(uint oldGagged) 231 { 232 bool anyErrs = (gaggedErrors != oldGagged); 233 --gag; 234 // Restore the original state of gagged errors; set total errors 235 // to be original errors + new ungagged errors. 236 errors -= (gaggedErrors - oldGagged); 237 gaggedErrors = oldGagged; 238 return anyErrs; 239 } 240 241 /* Increment the error count to record that an error 242 * has occured in the current context. An error message 243 * may or may not have been printed. 244 */ 245 extern (C++) void increaseErrorCount() 246 { 247 if (gag) 248 ++gaggedErrors; 249 ++errors; 250 } 251 252 extern (C++) void _init() 253 { 254 inifilename = null; 255 mars_ext = "d"; 256 hdr_ext = "di"; 257 doc_ext = "html"; 258 ddoc_ext = "ddoc"; 259 json_ext = "json"; 260 map_ext = "map"; 261 static if (TARGET_WINDOS) 262 { 263 obj_ext = "obj"; 264 } 265 else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 266 { 267 obj_ext = "o"; 268 } 269 else 270 { 271 static assert(0, "fix this"); 272 } 273 static if (TARGET_WINDOS) 274 { 275 lib_ext = "lib"; 276 } 277 else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 278 { 279 lib_ext = "a"; 280 } 281 else 282 { 283 static assert(0, "fix this"); 284 } 285 static if (TARGET_WINDOS) 286 { 287 dll_ext = "dll"; 288 } 289 else static if (TARGET_LINUX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 290 { 291 dll_ext = "so"; 292 } 293 else static if (TARGET_OSX) 294 { 295 dll_ext = "dylib"; 296 } 297 else 298 { 299 static assert(0, "fix this"); 300 } 301 static if (TARGET_WINDOS) 302 { 303 run_noext = false; 304 } 305 else static if (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS) 306 { 307 // Allow 'script' D source files to have no extension. 308 run_noext = true; 309 } 310 else 311 { 312 static assert(0, "fix this"); 313 } 314 copyright = "Copyright (c) 1999-2015 by Digital Mars"; 315 written = "written by Walter Bright"; 316 _version = "v2.071.0"; 317 compiler.vendor = "Digital Mars D"; 318 stdmsg = stdout; 319 main_d = "__main.d"; 320 errorLimit = 20; 321 } 322 } 323 324 // Because int64_t and friends may be any integral type of the 325 // correct size, we have to explicitly ask for the correct 326 // integer type to get the correct mangling with ddmd 327 328 // Be careful not to care about sign when using dinteger_t 329 // use this instead of integer_t to 330 // avoid conflicts with system #include's 331 alias dinteger_t = ulong; 332 // Signed and unsigned variants 333 alias sinteger_t = long; 334 alias uinteger_t = ulong; 335 336 alias d_int8 = int8_t; 337 alias d_uns8 = uint8_t; 338 alias d_int16 = int16_t; 339 alias d_uns16 = uint16_t; 340 alias d_int32 = int32_t; 341 alias d_uns32 = uint32_t; 342 alias d_int64 = int64_t; 343 alias d_uns64 = uint64_t; 344 alias d_float32 = float; 345 alias d_float64 = double; 346 alias d_float80 = real; 347 alias real_t = real; 348 349 // file location 350 struct Loc 351 { 352 const(char)* filename; 353 uint linnum; 354 uint charnum; 355 356 extern (D) this(const(char)* filename, uint linnum, uint charnum) 357 { 358 this.linnum = linnum; 359 this.charnum = charnum; 360 this.filename = filename; 361 } 362 363 extern (C++) const(char)* toChars() const 364 { 365 OutBuffer buf; 366 if (filename) 367 { 368 buf.printf("%s", filename); 369 } 370 if (linnum) 371 { 372 buf.printf("(%d", linnum); 373 if (global.params.showColumns && charnum) 374 buf.printf(",%d", charnum); 375 buf.writeByte(')'); 376 } 377 return buf.extractString(); 378 } 379 380 extern (C++) bool equals(ref const(Loc) loc) 381 { 382 return (!global.params.showColumns || charnum == loc.charnum) && linnum == loc.linnum && FileName.equals(filename, loc.filename); 383 } 384 } 385 386 enum LINK : int 387 { 388 def, // default 389 d, 390 c, 391 cpp, 392 windows, 393 pascal, 394 objc, 395 } 396 397 alias LINKdefault = LINK.def; 398 alias LINKd = LINK.d; 399 alias LINKc = LINK.c; 400 alias LINKcpp = LINK.cpp; 401 alias LINKwindows = LINK.windows; 402 alias LINKpascal = LINK.pascal; 403 alias LINKobjc = LINK.objc; 404 405 enum DYNCAST : int 406 { 407 object, 408 expression, 409 dsymbol, 410 type, 411 identifier, 412 tuple, 413 parameter, 414 } 415 416 alias DYNCAST_OBJECT = DYNCAST.object; 417 alias DYNCAST_EXPRESSION = DYNCAST.expression; 418 alias DYNCAST_DSYMBOL = DYNCAST.dsymbol; 419 alias DYNCAST_TYPE = DYNCAST.type; 420 alias DYNCAST_IDENTIFIER = DYNCAST.identifier; 421 alias DYNCAST_TUPLE = DYNCAST.tuple; 422 alias DYNCAST_PARAMETER = DYNCAST.parameter; 423 424 enum MATCH : int 425 { 426 nomatch, // no match 427 convert, // match with conversions 428 constant, // match with conversion to const 429 exact, // exact match 430 } 431 432 alias MATCHnomatch = MATCH.nomatch; 433 alias MATCHconvert = MATCH.convert; 434 alias MATCHconst = MATCH.constant; 435 alias MATCHexact = MATCH.exact; 436 437 enum PINLINE : int 438 { 439 def, // as specified on the command line 440 never, // never inline 441 always, // always inline 442 } 443 444 alias PINLINEdefault = PINLINE.def; 445 alias PINLINEnever = PINLINE.never; 446 alias PINLINEalways = PINLINE.always; 447 448 alias StorageClass = uinteger_t; 449 450 extern (C++) __gshared Global global;