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;