Intel® Implicit SPMD Program Compiler (Intel® ISPC)  1.13.0
sym.h
Go to the documentation of this file.
1 /*
2  Copyright (c) 2010-2019, Intel Corporation
3  All rights reserved.
4 
5  Redistribution and use in source and binary forms, with or without
6  modification, are permitted provided that the following conditions are
7  met:
8 
9  * Redistributions of source code must retain the above copyright
10  notice, this list of conditions and the following disclaimer.
11 
12  * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16  * Neither the name of Intel Corporation nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
22  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
24  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
25  OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33 
34 /** @file sym.h
35 
36  @brief header file with declarations for symbol and symbol table
37  classes.
38 */
39 
40 #pragma once
41 
42 #include "decl.h"
43 #include "ispc.h"
44 #include <map>
45 
46 class StructType;
47 class ConstExpr;
48 
49 /**
50  @brief Representation of a program symbol.
51 
52  The Symbol class represents a symbol in an ispc program. Symbols can
53  include variables, functions, and named types. Note that all of the
54  members are publically accessible; other code throughout the system
55  accesses and modifies the members directly.
56 
57  @todo Should we break function symbols into a separate FunctionSymbol
58  class and then not have these members that are not applicable for
59  function symbols (and vice versa, for non-function symbols)?
60  */
61 
62 class Symbol {
63  public:
64  /** The Symbol constructor takes the name of the symbol, its
65  position in a source file, and its type (if known). */
66  Symbol(const std::string &name, SourcePos pos, const Type *t = NULL, StorageClass sc = SC_NONE);
67 
68  SourcePos pos; /*!< Source file position where the symbol was defined */
69  std::string name; /*!< Symbol's name */
70  llvm::Value *storagePtr; /*!< For symbols with storage associated with
71  them (i.e. variables but not functions),
72  this member stores a pointer to its
73  location in memory.) */
74  llvm::Function *function; /*!< For symbols that represent functions,
75  this stores the LLVM Function value for
76  the symbol once it has been created. */
77  llvm::Function *exportedFunction;
78  /*!< For symbols that represent functions with
79  'export' qualifiers, this points to the LLVM
80  Function for the application-callable version
81  of the function. */
82  const Type *type; /*!< The type of the symbol; if not set by the
83  constructor, this is set after the
84  declaration around the symbol has been parsed. */
85  ConstExpr *constValue; /*!< For symbols with const-qualified types, this may store
86  the symbol's compile-time constant value. This value may
87  validly be NULL for a const-qualified type, however; for
88  example, the ConstExpr class can't currently represent
89  struct types. For cases like these, ConstExpr is NULL,
90  though for all const symbols, the value pointed to by the
91  storagePtr member will be its constant value. (This
92  messiness is due to needing an ispc ConstExpr for the early
93  constant folding optimizations). */
94  StorageClass storageClass; /*!< Records the storage class (if any) provided with the
95  symbol's declaration. */
96  int varyingCFDepth; /*!< This member records the number of levels of nested 'varying'
97  control flow within which the symbol was declared. Having
98  this value available makes it possible to avoid performing
99  masked stores when modifying the symbol's value when the
100  store is done at the same 'varying' control flow depth as
101  the one where the symbol was originally declared. */
103  /*!< For symbols that are parameters to functions or are
104  variables declared inside functions, this gives the
105  function they're in. */
106 };
107 
108 /** @brief Symbol table that holds all known symbols during parsing and compilation.
109 
110  A single instance of a SymbolTable is stored in the Module class
111  (Module::symbolTable); it is created in the Module::Module()
112  constructor. It is then accessed via the global variable Module *\ref m
113  throughout the ispc implementation.
114  */
115 
116 class SymbolTable {
117  public:
118  SymbolTable();
119  ~SymbolTable();
120 
121  /** The parser calls this method when it enters a new scope in the
122  program; this allows us to track variables that shadows others in
123  outer scopes with same name as well as to efficiently discard all
124  of the variables declared in a particular scope when we exit that
125  scope. */
126  void PushScope();
127 
128  /** For each scope started by a call to SymbolTable::PushScope(), there
129  must be a matching call to SymbolTable::PopScope() at the end of
130  that scope. */
131  void PopScope();
132 
133  /** Adds the given variable symbol to the symbol table.
134  @param symbol The symbol to be added
135 
136  @return true if successful; false if the provided symbol clashes
137  with a symbol defined at the same scope. (Symbols may shaodow
138  symbols in outer scopes; a warning is issued in this case, but this
139  method still returns true.) */
140  bool AddVariable(Symbol *symbol);
141 
142  /** Looks for a variable with the given name in the symbol table. This
143  method searches outward from the innermost scope to the outermost,
144  returning the first match found.
145 
146  @param name The name of the variable to be searched for.
147  @return A pointer to the Symbol, if a match is found. NULL if no
148  Symbol with the given name is in the symbol table. */
149  Symbol *LookupVariable(const char *name);
150 
151  /** Adds the given function symbol to the symbol table.
152  @param symbol The function symbol to be added.
153 
154  @return true if the symbol has been added. False if another
155  function symbol with the same name and function signature is
156  already present in the symbol table. */
157  bool AddFunction(Symbol *symbol);
158 
159  /** Looks for the function or functions with the given name in the
160  symbol name. If a function has been overloaded and multiple
161  definitions are present for a given function name, all of them will
162  be returned in the provided vector and it's up the the caller to
163  resolve which one (if any) to use. Returns true if any matches
164  were found. */
165  bool LookupFunction(const char *name, std::vector<Symbol *> *matches = NULL);
166 
167  /** Looks for a function with the given name and type
168  in the symbol table.
169 
170  @return pointer to matching Symbol; NULL if none is found. */
171  Symbol *LookupFunction(const char *name, const FunctionType *type);
172 
173  /** Returns all of the functions in the symbol table that match the given
174  predicate.
175 
176  @param pred A unary predicate that returns true or false, given a Symbol
177  pointer, based on whether the symbol should be included in the returned
178  set of matches. It can either be a function, with signature
179  <tt>bool pred(const Symbol *s)</tt>, or a unary predicate object with
180  an <tt>bool operator()(const Symbol *)</tt> method.
181 
182  @param matches Pointer to a vector in which to return the matching
183  symbols.
184  */
185  template <typename Predicate> void GetMatchingFunctions(Predicate pred, std::vector<Symbol *> *matches) const;
186 
187  /** Returns all of the variable symbols in the symbol table that match
188  the given predicate. The predicate is defined as in the
189  GetMatchingFunctions() method.
190  */
191  template <typename Predicate> void GetMatchingVariables(Predicate pred, std::vector<Symbol *> *matches) const;
192 
193  /** Adds the named type to the symbol table. This is used for both
194  struct definitions (where <tt>struct Foo</tt> causes type \c Foo to
195  be added to the symbol table) as well as for <tt>typedef</tt>s.
196  For structs with forward declarations ("struct Foo;") and are thus
197  UndefinedStructTypes, this method replaces these with an actual
198  struct definition if one is provided.
199 
200  @param name Name of the type to be added
201  @param type Type that \c name represents
202  @param pos Position in source file where the type was named
203  @return true if the named type was successfully added. False if a type
204  with the same name has already been defined.
205 
206  */
207  bool AddType(const char *name, const Type *type, SourcePos pos);
208 
209  /** Looks for a type of the given name in the symbol table.
210 
211  @return Pointer to the Type, if found; otherwise NULL is returned.
212  */
213  const Type *LookupType(const char *name) const;
214 
215  /** Look for a type given a pointer.
216 
217  @return True if found, False otherwise.
218  */
219  bool ContainsType(const Type *type) const;
220 
221  /** This method returns zero or more strings with the names of symbols
222  in the symbol table that nearly (but not exactly) match the given
223  name. This is useful for issuing informative error methods when
224  misspelled identifiers are found a programs.
225 
226  @param name String to compare variable and function symbol names against.
227  @return vector of zero or more strings that approximately match \c name.
228  */
229  std::vector<std::string> ClosestVariableOrFunctionMatch(const char *name) const;
230  /** This method returns zero or more strings with the names of types
231  in the symbol table that nearly (but not exactly) match the given
232  name. */
233  std::vector<std::string> ClosestTypeMatch(const char *name) const;
234 
235  std::vector<std::string> ClosestEnumTypeMatch(const char *name) const;
236 
237  /** Prints out the entire contents of the symbol table to standard error.
238  (Debugging method). */
239  void Print();
240 
241  /** Returns a random symbol from the symbol table. (It is not
242  guaranteed that it is equally likely to return all symbols). */
243  Symbol *RandomSymbol();
244 
245  /** Returns a random type from the symbol table. */
246  const Type *RandomType();
247 
248  private:
249  std::vector<std::string> closestTypeMatch(const char *str, bool structsVsEnums) const;
250 
251  /** This member variable holds one SymbolMap for each of the current
252  active scopes as the program is being parsed. New maps are added
253  and removed from the end of the main vector, so searches for
254  symbols start looking at the end of \c variables and work
255  backwards.
256  */
257  typedef std::map<std::string, Symbol *> SymbolMapType;
258  std::vector<SymbolMapType *> variables;
259 
260  std::vector<SymbolMapType *> freeSymbolMaps;
261 
262  /** Function declarations are *not* scoped. (C99, for example, allows
263  an implementation to maintain function declarations in a single
264  namespace.) A STL \c vector is used to store the function symbols
265  for a given name since, due to function overloading, a name can
266  have multiple function symbols associated with it. */
267  typedef std::map<std::string, std::vector<Symbol *>> FunctionMapType;
268  FunctionMapType functions;
269 
270  /** Type definitions can't currently be scoped.
271  */
272  typedef std::map<std::string, const Type *> TypeMapType;
273  TypeMapType types;
274 };
275 
276 template <typename Predicate>
277 void SymbolTable::GetMatchingFunctions(Predicate pred, std::vector<Symbol *> *matches) const {
278  // Iterate through all function symbols and apply the given predicate.
279  // If it returns true, add the Symbol * to the provided vector.
280  FunctionMapType::const_iterator iter;
281  for (iter = functions.begin(); iter != functions.end(); ++iter) {
282  const std::vector<Symbol *> &syms = iter->second;
283  for (unsigned int j = 0; j < syms.size(); ++j) {
284  if (pred(syms[j]))
285  matches->push_back(syms[j]);
286  }
287  }
288 }
289 
290 template <typename Predicate>
291 void SymbolTable::GetMatchingVariables(Predicate pred, std::vector<Symbol *> *matches) const {
292  for (unsigned int i = 0; i < variables.size(); ++i) {
293  SymbolMapType &sm = *(variables[i]);
294  SymbolMapType::const_iterator iter;
295  for (iter = sm.begin(); iter != sm.end(); ++iter) {
296  if (pred(iter->second))
297  matches->push_back(iter->second);
298  }
299  }
300 }
llvm::Value * storagePtr
Definition: sym.h:70
Definition: func.h:43
std::map< std::string, const Type * > TypeMapType
Definition: sym.h:272
Expression representing a compile-time constant value.
Definition: expr.h:374
Symbol table that holds all known symbols during parsing and compilation.
Definition: sym.h:116
FunctionMapType functions
Definition: sym.h:268
std::string name
Definition: sym.h:69
ConstExpr * constValue
Definition: sym.h:85
TypeMapType types
Definition: sym.h:273
std::vector< SymbolMapType * > freeSymbolMaps
Definition: sym.h:260
Symbol(const std::string &name, SourcePos pos, const Type *t=NULL, StorageClass sc=SC_NONE)
Definition: sym.cpp:46
void GetMatchingVariables(Predicate pred, std::vector< Symbol *> *matches) const
Definition: sym.h:291
std::map< std::string, std::vector< Symbol * > > FunctionMapType
Definition: sym.h:267
std::vector< SymbolMapType * > variables
Definition: sym.h:258
Representation of a structure holding a number of members.
Definition: type.h:650
SourcePos pos
Definition: sym.h:68
StorageClass storageClass
Definition: sym.h:94
Representation of a range of positions in a source file.
Definition: ispc.h:123
Declarations related to type declarations; the parser basically creates instances of these classes...
StorageClass
Definition: ispc.h:114
Definition: ispc.h:114
std::map< std::string, Symbol * > SymbolMapType
Definition: sym.h:257
Type representing a function (return type + argument types)
Definition: type.h:829
Representation of a program symbol.
Definition: sym.h:62
int varyingCFDepth
Definition: sym.h:96
Interface class that defines the type abstraction.
Definition: type.h:90
void GetMatchingFunctions(Predicate pred, std::vector< Symbol *> *matches) const
Definition: sym.h:277
const Function * parentFunction
Definition: sym.h:102
const Type * type
Definition: sym.h:82
Main ispc.header file. Defines Target, Globals and Opt classes.
llvm::Function * exportedFunction
Definition: sym.h:77