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;