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