amd64: Spell amd64 as AMD64 in macro names.
[libfirm] / scripts / spec_util.py
1 # This file is part of libFirm.
2 # Copyright (C) 2012 Karlsruhe Institute of Technology.
3 import sys
4 import imp
5
6 abstracts = set()
7 def abstract(cls):
8         abstracts.add(cls)
9         return cls
10 def isAbstract(nodetype):
11         return nodetype in abstracts
12
13 def op(cls):
14         cls.__is_firm_op = True
15         return cls
16 def isOp(nodetype):
17         return hasattr(nodetype, "__is_firm_op")
18
19 def is_dynamic_pinned(node):
20         return node.pinned in ["memory", "exception"]
21
22 def is_fragile(node):
23         return hasattr(node, "flags") and "fragile" in node.flags
24
25 def inout_contains(l, name):
26         for entry in l:
27                 if entry[0] == name:
28                         return True
29         return False
30
31 def verify_node(node):
32         if not hasattr(node, "pinned"):
33                 print "%s: NO PINNED SET" % node.name
34         elif node.pinned not in ["yes", "no", "memory", "exception"]:
35                 print "%s: UNKNOWN PINNED MODE: %s" % (node.name, node.pinned)
36
37         if not hasattr(node, "flags"):
38                 if not isAbstract(node):
39                         print "WARNING: no flags specified for %s\n" % node.name
40         elif type(node.flags) != list:
41                 print "ERROR: flags of %s not a list" % node.name
42
43         if hasattr(node, "pinned_init") and not is_dynamic_pinned(node):
44                 print "ERROR: node %s has pinned_init attribute but is not marked as dynamically pinned" % node.name
45         if hasattr(node, "flags") and "uses_memory" in node.flags:
46                 if not inout_contains(node.ins, "mem"):
47                         print "ERROR: memory op %s needs an input named 'mem'" % node.name
48         if is_fragile(node):
49                 if not is_dynamic_pinned(node):
50                         print "ERROR: fragile node %s must be dynamically pinned" % node.name
51                 if not hasattr(node, "throws_init"):
52                         print "ERROR: fragile node %s needs a throws_init attribute" % node.name
53                 if not inout_contains(node.outs, "X_regular"):
54                         print "ERROR: fragile node %s needs an output named 'X_regular'" % node.name
55                 if not inout_contains(node.outs, "X_except"):
56                         print "ERROR: fragile node %s needs an output named 'X_except'" % node.name
57         else:
58                 if hasattr(node, "throws_init"):
59                         print "ERROR: throws_init only makes sense for fragile nodes"
60
61
62 def setldefault(node, attr, val):
63         # Don't use hasattr, as these things should not be inherited
64         if attr not in node.__dict__:
65                 setattr(node, attr, val)
66
67 def setdefault(node, attr, val):
68         # Don't use hasattr, as these things should not be inherited
69         if not hasattr(node, attr):
70                 setattr(node, attr, val)
71
72 def setnodedefaults(node):
73         setldefault(node, "name", node.__name__)
74         if isAbstract(node):
75                 return
76
77         setdefault(node, "ins", [])
78         setdefault(node, "arity", len(node.ins))
79         setdefault(node, "attrs", [])
80         setdefault(node, "constructor_args", [])
81         setdefault(node, "customSerializer", False)
82         if hasattr(node, "__doc__"):
83                 node.doc = trim_docstring(node.__doc__)
84         else:
85                 node.doc = ""
86         if hasattr(node, "outs"):
87                 node.mode = "mode_T"
88
89 def load_spec(filename):
90         module = imp.load_source('spec', filename)
91         nodes = []
92         for x in module.__dict__.values():
93                 if not isOp(x):
94                         continue
95                 setnodedefaults(x)
96                 verify_node(x)
97                 nodes.append(x)
98         nodes.sort(key=lambda x: x.name)
99         module.nodes = nodes
100         if len(nodes) == 0:
101                 print "Warning: No nodes found in spec file '%s'" % filename
102         if not hasattr(module, "name"):
103                 print "Warning: No name specified in file '%s'" % filename
104         return module
105
106 def trim_docstring(docstring):
107     if not docstring:
108         return ''
109     # Convert tabs to spaces (following the normal Python rules)
110     # and split into a list of lines:
111     lines = docstring.expandtabs().splitlines()
112     # Determine minimum indentation (first line doesn't count):
113     indent = sys.maxint
114     for line in lines[1:]:
115         stripped = line.lstrip()
116         if stripped:
117             indent = min(indent, len(line) - len(stripped))
118     # Remove indentation (first line is special):
119     trimmed = [lines[0].strip()]
120     if indent < sys.maxint:
121         for line in lines[1:]:
122             trimmed.append(line[indent:].rstrip())
123     # Strip off trailing and leading blank lines:
124     while trimmed and not trimmed[-1]:
125         trimmed.pop()
126     while trimmed and not trimmed[0]:
127         trimmed.pop(0)
128     # Return a single string:
129     return '\n'.join(trimmed)