1 /* Jitter: general-purpose CPP macros for stringification and concatenation.
2 
3    Copyright (C) 2017, 2021 Luca Saiu
4    Updated in 2019 by Luca Saiu
5    Written by Luca Saiu
6 
7    This file is part of Jitter.
8 
9    Jitter is free software: you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation, either version 3 of the License, or
12    (at your option) any later version.
13 
14    Jitter is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with Jitter.  If not, see <http://www.gnu.org/licenses/>. */
21 
22 
23 #ifndef JITTER_CPP_H_
24 #define JITTER_CPP_H_
25 
26 /* This entire header has no dependencies and expands to nothing, by design.  It
27    is safe to include from assembly sources. */
28 
29 /* Remark on multiple-level expansion.
30  * ************************************************************************** */
31 
32 /* Yes, these two-levels of macros are needed; see the (excellent) GNU CPP
33    manual.  The resulting clumsiness is the real reason why the macros in this
34    header are useful. */
35 
36 
37 
38 
39 /* Convenient stringification.
40  * ************************************************************************** */
41 
42 /* Expand to the stringification of the macro parameter, itself unexpanded.
43    This is not intended for the user. */
44 #define JITTER_STRINGIFY_UNEXPANDED(whatever)  \
45   # whatever
46 
47 /* Expand to the stringification of the macro parameter, after it is expanded
48    itself. */
49 #define JITTER_STRINGIFY(whatever)       \
50   JITTER_STRINGIFY_UNEXPANDED(whatever)
51 
52 
53 
54 
55 /* Convenient token concatenation.
56  * ************************************************************************** */
57 
58 /* Expand to the token concatentation of the given macro parameters, unexpanded.
59    These are not intended for the user. */
60 #define JITTER_CONCATENATE_TWO_UNEXPANDED(a, b)  \
61   a ## b
62 #define JITTER_CONCATENATE_THREE_UNEXPANDED(a, b, c)  \
63   a ## b ## c
64 #define JITTER_CONCATENATE_FOUR_UNEXPANDED(a, b, c, d)  \
65   a ## b ## c ## d
66 #define JITTER_CONCATENATE_FIVE_UNEXPANDED(a, b, c, d, e)  \
67   a ## b ## c ## d ## e
68 
69 /* Expand to the token concatentation of the given macro parameters, after they
70    are expanded themselves. */
71 #define JITTER_CONCATENATE_TWO(a, b)  \
72   JITTER_CONCATENATE_TWO_UNEXPANDED(a, b)
73 #define JITTER_CONCATENATE_THREE(a, b, c)  \
74   JITTER_CONCATENATE_THREE_UNEXPANDED(a, b, c)
75 #define JITTER_CONCATENATE_FOUR(a, b, c, d)  \
76   JITTER_CONCATENATE_FOUR_UNEXPANDED(a, b, c, d)
77 #define JITTER_CONCATENATE_FIVE(a, b, c, d, e)  \
78   JITTER_CONCATENATE_FIVE_UNEXPANDED(a, b, c, d, e)
79 
80 
81 
82 
83 /* Local identifier poisoning.
84  * ************************************************************************** */
85 
86 /* This feature serves to provide helpful error messages in case a code block
87    contains a use of a locally forbidden identifier.  The identifier is poisoned
88    at the beginning of the block and unpoisoned at the end.
89    It is possible to poison functions, non-function globals, macros, and even C
90    keywords.
91 
92    The implementation relies on non-standard GNU C features.  It is used
93    conditionally in generated code.  Where the feature is not supported the
94    system will fail in a less friendly way in case of incorrect code, but
95    correctness will not be compromised. */
96 
97 /* This is how to poison an indentifier foo, for example with the error message
98    about relocatable VM instructions::
99 #    pragma push_macro ("foo")
100 #    undef foo
101 #    define foo JITTER_FORBIDDEN_EXPRESSION_IN_RELOCATABLE (foo)
102 
103    And this is how to unpoison it:
104 #    pragma pop_macro ("foo")
105 
106    In order to avoid spurious warning messages at the beginning of a sequence
107    of poisonings, this should be generated (once):
108 #    pragma GCC diagnostic push
109 #    pragma GCC diagnostic ignored "-Wpragmas"
110 #    pragma GCC diagnostic ignored "-Wunknown-warning-option"
111 #    pragma GCC diagnostic ignored "-Wbuiltin-macro-redefined"
112 #    pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch"
113    At the end, after unpoisoning, this restores the previous diagnostics state:
114 #    pragma GCC diagnostic pop  */
115 
116 /* The canonic use of _Pragma with a stringized argument. */
117 #define JITTER_PRAGMA(x)  \
118   _Pragma (#x)
119 
120 /* Expand to a sequence of two _Pragma uses, the first one printing a nice error
121    message involving the given identifier and the given message (provided by the
122    caller as a string), the second one causing the compiler to fail. */
123 #define JITTER_PRAGMA_WARN_WITH_REASON(identifier, reason_string_literal)      \
124   /* This is printed in a nicer way than #pragma GCC error. */                 \
125   JITTER_PRAGMA (message ("\nYou cannot use \"" # identifier "\" in "          \
126                           JITTER_SPECIALIZED_INSTRUCTION_NAME_AS_STRING ":\n"  \
127                           reason_string_literal                                \
128                           ".\nAny type error you may see after this "          \
129                           "message is probably an effect of this macro "       \
130                           "which serves to prevent the use of "                \
131                           "\"" #identifier "\"."                               \
132                           ));                                                  \
133   /* And now fail, as well.  This literal string is printed nicely. */         \
134   JITTER_PRAGMA (GCC error "Refusing to compile.");
135 
136 /* Expand to a use of JITTER_PRAGMA_WARN_WITH_REASON with the appropriate error
137    message. */
138 #define JITTER_POISONED_IN_ANY_INSTRUCTION(identifier)      \
139   JITTER_PRAGMA_WARN_WITH_REASON                            \
140      (identifier, "it is forbidden in any VM instruction")
141 #define JITTER_POISONED_IN_RELOCATABLE_INSTRUCTION(identifier)        \
142   JITTER_PRAGMA_WARN_WITH_REASON                                      \
143      (identifier,                                                     \
144       "it is forbidden in relocatable VM instructions (but you may "  \
145       "change the instruction to be non-relocatable)")
146 #define JITTER_POISONED_IN_NON_BRANCHING_INSTRUCTION(identifier)        \
147   JITTER_PRAGMA_WARN_WITH_REASON                                      \
148      (identifier,                                                     \
149       "it is forbidden in non-branching VM instructions (but you may "  \
150       "change the instruction to be branching)")
151 
152 /* Expand to a GNU C statement-expresison evaluating to zero (which is
153    compatible with most types in C) and a use of JITTER_PRAGMA_WARN_WITH_REASON.
154    The fact that the identifier expands to an expression makes it likely that
155    the resulting expression remains well-formed syntactically, which avoids
156    distracting syntax errors in many cases.
157    The intended error message related to the use of the identifier is printend
158    in any case. */
159 #define JITTER_FORBIDDEN_EXPRESSION(identifier)                      \
160   ({ JITTER_POISONED_IN_ANY_INSTRUCTION (identifier); 0; })
161 #define JITTER_FORBIDDEN_EXPRESSION_IN_RELOCATABLE(identifier)       \
162   ({ JITTER_POISONED_IN_RELOCATABLE_INSTRUCTION (identifier); 0; })
163 #define JITTER_FORBIDDEN_EXPRESSION_IN_NON_BRANCHING(identifier)       \
164   ({ JITTER_POISONED_IN_NON_BRANCHING_INSTRUCTION (identifier); 0; })
165 
166 #endif // #ifndef JITTER_CPP_H_
167