1
from pypy.rpython.lltypesystem import lltype
2
from pypy.translator.gensupp import NameManager
5
# use __slots__ declarations for node classes etc
6
# possible to turn it off while refactoring, experimenting
10
PyObjPtr = lltype.Ptr(lltype.PyObject)
14
def __init__(self, TYPE):
21
def cdecl(ctype, cname, is_thread_local=False):
23
Produce a C declaration from a 'type template' and an identifier.
24
The type template must contain a '@' sign at the place where the
25
name should be inserted, according to the strange C syntax rules.
27
# the (@) case is for functions, where if there is a plain (@) around
28
# the function name, we don't need the very confusing parenthesis
31
__thread = "__thread "
32
return __thread + ctype.replace('(@)', '@').replace('@', cname).strip()
34
def forward_cdecl(ctype, cname, standalone, is_thread_local=False):
37
__thread = "__thread "
39
cdecl_str = __thread + cdecl(ctype, cname)
41
return 'extern ' + cdecl_str
45
def somelettersfrom(s):
46
upcase = [c for c in s if c.isupper()]
48
upcase = [c for c in s.title() if c.isupper()]
49
locase = [c for c in s if c.islower()]
51
return ''.join(upcase).lower()
56
def llvalue_from_constant(c):
59
except AttributeError:
61
if T == PyObjPtr and not isinstance(c.value, lltype._ptr):
62
return lltype.pyobjectptr(c.value)
67
assert lltype.typeOf(c.value) == T
71
class CNameManager(NameManager):
72
def __init__(self, global_prefix='pypy_'):
73
NameManager.__init__(self, global_prefix=global_prefix)
74
# keywords cannot be reused. This is the C99 draft's list.
75
self.make_reserved_names('''
76
auto enum restrict unsigned
77
break extern return void
78
case float short volatile
80
const goto sizeof _Bool
81
continue if static _Complex
82
default inline struct _Imaginary
89
if c in '\\"': return '\\' + c
90
if ' ' <= c < '\x7F': return c
91
return '\\%03o' % ord(c)
94
return ''.join([_char_repr(c) for c in s])
97
def c_string_constant(s):
98
'''Returns a " "-delimited string literal for C.'''
100
for i in range(0, len(s), 64):
101
lines.append('"%s"' % _line_repr(s[i:i+64]))
102
return '\n'.join(lines)
105
def c_char_array_constant(s):
106
'''Returns an initializer for a constant char[N] array,
107
where N is exactly len(s). This is either a " "-delimited
108
string or a { }-delimited array of small integers.
110
if s.endswith('\x00') and len(s) < 1024:
111
# C++ is stricted than C: we can only use a " " literal
112
# if the last character is NULL, because such a literal
113
# always has an extra implicit NULL terminator.
114
return c_string_constant(s[:-1])
117
for i in range(0, len(s), 20):
118
lines.append(','.join([str(ord(c)) for c in s[i:i+20]]))
120
return '{\n%s}' % ',\n'.join(lines)
122
return '{%s}' % ', '.join(lines)
125
##def gen_assignments(assignments):
126
## # Generate a sequence of assignments that is possibly reordered
127
## # to avoid clashes -- i.e. do the equivalent of a tuple assignment,
128
## # reading all sources first, writing all targets next, but optimized
133
## for typename, dest, src in assignments:
134
## if src != dest: # ignore 'v=v;'
135
## allsources.append(src)
136
## src2dest.setdefault(src, []).append(dest)
137
## types[dest] = typename
139
## for starting in allsources:
140
## # starting from some starting variable, follow a chain of assignments
141
## # 'vn=vn-1; ...; v3=v2; v2=v1; v1=starting;'
144
## while src2dest.get(v):
145
## srcchain.append(v)
146
## v = src2dest[v].pop(0)
150
## continue # already done in a previous chain
151
## srcchain.reverse() # ['vn-1', ..., 'v2', 'v1', 'starting']
153
## for pair in zip([v] + srcchain[:-1], srcchain):
154
## code.append('%s = %s;' % pair)
156
## # assignment loop 'starting=vn-1; ...; v2=v1; v1=starting;'
157
## typename = types[starting]
158
## tmpdecl = cdecl(typename, 'tmp')
159
## code.insert(0, '{ %s = %s;' % (tmpdecl, starting))
160
## code[-1] = '%s = tmp; }' % (srcchain[-2],)
161
## yield ' '.join(code)
163
def gen_assignments(assignments):
164
# Generate a sequence of assignments that is possibly reordered
165
# to avoid clashes -- i.e. do the equivalent of a tuple assignment,
166
# reading all sources first, writing all targets next, but optimized
170
for typename, dest, src in assignments:
171
if src != dest: # ignore 'v=v;'
172
srccount[src] = srccount.get(src, 0) + 1
173
dest2src[dest] = src, typename
177
for dst in dest2src.keys():
178
if dst not in srccount:
179
src, typename = dest2src.pop(dst)
180
yield '%s = %s;' % (dst, src)
182
if not srccount[src]:
186
# we are left with only pure disjoint cycles; break them
188
dst, (src, typename) = dest2src.popitem()
189
assert srccount[dst] == 1
191
tmpdecl = cdecl(typename, 'tmp')
192
code = ['{ %s = %s;' % (tmpdecl, dst)]
193
while src is not startingpoint:
194
code.append('%s = %s;' % (dst, src))
196
src, typename = dest2src.pop(dst)
197
assert srccount[dst] == 1
198
code.append('%s = tmp; }' % (dst,))
204
from pypy.tool.ansi_print import ansi_log
205
log = py.log.Producer("c")
206
py.log.setconsumer("c", ansi_log)