Wire Sysio Wire Sysion 1.0.0
Loading...
Searching...
No Matches
WAST Namespace Reference

Classes

struct  Action
 
struct  ActionCommand
 
struct  AssertInvalidOrMalformedCommand
 
struct  AssertReturnCommand
 
struct  AssertReturnNaNCommand
 
struct  AssertTrapCommand
 
struct  AssertUnlinkableCommand
 
struct  Command
 
struct  Error
 
struct  FatalParseException
 
struct  FunctionPrintContext
 
struct  GetAction
 
struct  InvokeAction
 
struct  LineInfo
 
struct  ModuleAction
 
struct  ModuleParseState
 
struct  ModulePrintContext
 
struct  Name
 
struct  NameScope
 
struct  ParseState
 
struct  RecoverParseException
 
struct  Reference
 
struct  RegisterCommand
 
struct  ScopedTagPrinter
 
struct  StaticData
 
struct  TextFileLocus
 
struct  UnresolvedError
 
struct  UnresolvedFunctionType
 

Typedefs

typedef std::unordered_map< Name, U32, Name::HasherNameToIndexMap
 

Enumerations

enum class  ActionType { _module , invoke , get }
 
enum  TokenType : U16 { numTokenTypes }
 

Functions

WAST_API void parseTestCommands (const char *string, Uptr stringLength, std::vector< std::unique_ptr< Command > > &outTestCommands, std::vector< Error > &outErrors)
 
WAST_API bool parseModule (const char *string, Uptr stringLength, IR::Module &outModule, std::vector< Error > &outErrors)
 
WAST_API std::string print (const IR::Module &module)
 
const char * describeToken (TokenType tokenType)
 
bool isRecoveryPointChar (char c)
 
Token * lex (const char *string, Uptr stringLength, LineInfo *&outLineInfo)
 
void freeTokens (Token *tokens)
 
void freeLineInfo (LineInfo *lineInfo)
 
TextFileLocus calcLocusFromOffset (const char *string, const LineInfo *lineInfo, Uptr charOffset)
 
 PACKED_STRUCT (struct Token { TokenType type;U32 begin;})
 
void findClosingParenthesis (ParseState &state, const Token *openingParenthesisToken)
 
void parseErrorf (ParseState &state, Uptr charOffset, const char *messageFormat, va_list messageArguments)
 
void parseErrorf (ParseState &state, Uptr charOffset, const char *messageFormat,...)
 
void parseErrorf (ParseState &state, const char *nextChar, const char *messageFormat,...)
 
void parseErrorf (ParseState &state, const Token *nextToken, const char *messageFormat,...)
 
void require (ParseState &state, TokenType type)
 
bool tryParseValueType (ParseState &state, ValueType &outValueType)
 
bool tryParseResultType (ParseState &state, ResultType &outResultType)
 
ValueType parseValueType (ParseState &state)
 
const FunctionTypeparseFunctionType (ModuleParseState &state, NameToIndexMap &outLocalNameToIndexMap, std::vector< std::string > &outLocalDisassemblyNames)
 
UnresolvedFunctionType parseFunctionTypeRefAndOrDecl (ModuleParseState &state, NameToIndexMap &outLocalNameToIndexMap, std::vector< std::string > &outLocalDisassemblyNames)
 
IndexedFunctionType resolveFunctionType (ModuleParseState &state, const UnresolvedFunctionType &unresolvedType)
 
IndexedFunctionType getUniqueFunctionTypeIndex (ModuleParseState &state, const FunctionType *functionType)
 
bool tryParseName (ParseState &state, Name &outName)
 
bool tryParseNameOrIndexRef (ParseState &state, Reference &outRef)
 
U32 parseAndResolveNameOrIndexRef (ParseState &state, const NameToIndexMap &nameToIndexMap, Uptr maxIndex, const char *context)
 
void bindName (ParseState &state, NameToIndexMap &nameToIndexMap, const Name &name, Uptr index)
 
U32 resolveRef (ParseState &state, const NameToIndexMap &nameToIndexMap, Uptr maxIndex, const Reference &ref)
 
bool tryParseHexit (const char *&nextChar, U8 &outValue)
 
bool tryParseString (ParseState &state, std::string &outString)
 
std::string parseUTF8String (ParseState &state)
 
bool tryParseI32 (ParseState &state, U32 &outI32)
 
bool tryParseI64 (ParseState &state, U64 &outI64)
 
U8 parseI8 (ParseState &state)
 
U32 parseI32 (ParseState &state)
 
U64 parseI64 (ParseState &state)
 
F32 parseF32 (ParseState &state)
 
F64 parseF64 (ParseState &state)
 
IR::FunctionDef parseFunctionDef (ModuleParseState &state, const Token *funcToken)
 
void parseModuleBody (ModuleParseState &state)
 
char nibbleToHexChar (U8 value)
 
std::string escapeString (const char *string, Uptr numChars)
 
std::string expandIndentation (std::string &&inString, U8 spacesPerIndentLevel=2)
 
void print (std::string &string, ValueType type)
 
void print (std::string &string, ResultType type)
 
void print (std::string &string, const SizeConstraints &size)
 
void print (std::string &string, const FunctionType *functionType)
 
void print (std::string &string, const TableType &type)
 
void print (std::string &string, const MemoryType &type)
 
void print (std::string &string, GlobalType type)
 
void printControlSignature (std::string &string, ResultType resultType)
 
template<typename Type >
void printImportType (std::string &string, const Module &module, Type type)
 
template<>
void printImportType< IndexedFunctionType > (std::string &string, const Module &module, IndexedFunctionType type)
 
template<typename Type >
void printImport (std::string &string, const Module &module, const Import< Type > &import, Uptr importIndex, const char *name, const char *typeTag)
 

Typedef Documentation

◆ NameToIndexMap

typedef std::unordered_map<Name,U32,Name::Hasher> WAST::NameToIndexMap

Definition at line 88 of file Parse.h.

Enumeration Type Documentation

◆ ActionType

enum class WAST::ActionType
strong
Enumerator
_module 
invoke 
get 

Definition at line 41 of file TestScript.h.

42 {
43 _module,
44 invoke,
45 get,
46 };

◆ TokenType

Enumerator
numTokenTypes 

Definition at line 87 of file Lexer.h.

88 {
89 #define VISIT_TOKEN(name,description) t_##name,
91 #undef VISIT_TOKEN
93 };
#define ENUM_TOKENS()
Definition Lexer.h:62
@ numTokenTypes
Definition Lexer.h:92

Function Documentation

◆ bindName()

void WAST::bindName ( ParseState & state,
NameToIndexMap & nameToIndexMap,
const Name & name,
Uptr index )

Definition at line 322 of file Parse.cpp.

323 {
324 errorUnless(index <= UINT32_MAX);
325
326 if(name)
327 {
328 auto mapIt = nameToIndexMap.find(name);
329 if(mapIt != nameToIndexMap.end())
330 {
331 const TextFileLocus previousDefinitionLocus = calcLocusFromOffset(state.string, state.lineInfo,mapIt->first.getCharOffset(state.string));
332 parseErrorf(state,name.getCharOffset(state.string),"redefinition of name defined at %s",previousDefinitionLocus.describe().c_str());
333 }
334 nameToIndexMap.emplace(name,U32(index));
335 }
336 }
uint32_t U32
Definition BasicTypes.h:9
#define errorUnless(condition)
Definition Errors.h:27
std::string name
TextFileLocus calcLocusFromOffset(const char *string, const LineInfo *lineInfo, Uptr charOffset)
Definition Lexer.cpp:331
void parseErrorf(ParseState &state, Uptr charOffset, const char *messageFormat, va_list messageArguments)
Definition Parse.cpp:45
#define UINT32_MAX
Definition stdint.h:188
std::string describe(U32 spacesPerTab=4) const
Definition WAST.h:26
Here is the call graph for this function:
Here is the caller graph for this function:

◆ calcLocusFromOffset()

TextFileLocus WAST::calcLocusFromOffset ( const char * string,
const LineInfo * lineInfo,
Uptr charOffset )

Definition at line 331 of file Lexer.cpp.

332 {
333 // Binary search the line starts for the last one before charIndex.
334 Uptr minLineIndex = 0;
335 Uptr maxLineIndex = lineInfo->numLineStarts - 1;
336 while(maxLineIndex > minLineIndex)
337 {
338 const Uptr medianLineIndex = (minLineIndex + maxLineIndex + 1) / 2;
339 if(charOffset < lineInfo->lineStarts[medianLineIndex])
340 {
341 maxLineIndex = medianLineIndex - 1;
342 }
343 else if(charOffset > lineInfo->lineStarts[medianLineIndex])
344 {
345 minLineIndex = medianLineIndex;
346 }
347 else
348 {
349 minLineIndex = maxLineIndex = medianLineIndex;
350 }
351 };
352 TextFileLocus result;
353 result.newlines = (U32)minLineIndex;
354
355 // Count tabs and and spaces from the beginning of the line to charIndex.
356 for(U32 index = lineInfo->lineStarts[result.newlines];index < charOffset;++index)
357 {
358 if(string[index] == '\t') { ++result.tabs; }
359 else { ++result.characters; }
360 }
361
362 // Copy the full source line into the TextFileLocus for context.
363 const Uptr lineStartOffset = getLineOffset(lineInfo,result.newlines);
364 Uptr lineEndOffset = getLineOffset(lineInfo,result.newlines+1) - 1;
365 result.sourceLine = std::string(string + lineStartOffset,lineEndOffset - lineStartOffset);
366
367 return result;
368 }
PointerIntHelper< sizeof(size_t)>::UnsignedIntType Uptr
Definition BasicTypes.h:22
U32 numLineStarts
Definition Lexer.cpp:150
U32 * lineStarts
Definition Lexer.cpp:149
Here is the caller graph for this function:

◆ describeToken()

const char * WAST::describeToken ( TokenType tokenType)

Definition at line 14 of file Lexer.cpp.

15 {
16 WAVM_ASSERT_THROW(tokenType < numTokenTypes);
17 static const char* tokenDescriptions[] =
18 {
19 // This ENUM_TOKENS must come before the literalTokenPairs definition that redefines VISIT_OPERATOR_TOKEN.
20 #define VISIT_TOKEN(name,description) description,
22 #undef VISIT_TOKEN
23 };
24 return tokenDescriptions[tokenType];
25 }
#define WAVM_ASSERT_THROW(cond)
Definition Errors.h:29
Here is the caller graph for this function:

◆ escapeString()

std::string WAST::escapeString ( const char * string,
Uptr numChars )

Definition at line 18 of file Print.cpp.

19 {
20 std::string result;
21 for(Uptr charIndex = 0;charIndex < numChars;++charIndex)
22 {
23 auto c = string[charIndex];
24 if(c == '\\') { result += "\\\\"; }
25 else if(c == '\"') { result += "\\\""; }
26 else if(c == '\n') { result += "\\n"; }
27 else if(c < 0x20 || c > 0x7e)
28 {
29 result += '\\';
30 result += nibbleToHexChar((c & 0xf0) >> 4);
31 result += nibbleToHexChar((c & 0x0f) >> 0);
32 }
33 else { result += c; }
34 }
35 return result;
36 }
char nibbleToHexChar(U8 value)
Definition NFA.cpp:397
Here is the call graph for this function:
Here is the caller graph for this function:

◆ expandIndentation()

std::string WAST::expandIndentation ( std::string && inString,
U8 spacesPerIndentLevel = 2 )

Definition at line 38 of file Print.cpp.

39 {
40 std::string paddedInput = std::move(inString);
41 paddedInput += '\0';
42
43 std::string result;
44 const char* next = paddedInput.data();
45 const char* end = paddedInput.data() + paddedInput.size() - 1;
46 Uptr indentDepth = 0;
47 while(next < end)
48 {
49 // Absorb INDENT_STRING and DEDENT_STRING, but keep track of the indentation depth,
50 // and insert a proportional number of spaces following newlines.
51 if(*(U16*)next == *(U16*)INDENT_STRING) { ++indentDepth; next += 2; }
52 else if(*(U16*)next == *(U16*)DEDENT_STRING) { errorUnless(indentDepth > 0); --indentDepth; next += 2; }
53 else if(*next == '\n')
54 {
55 result += '\n';
56 result.insert(result.end(),indentDepth*2,' ');
57 ++next;
58 }
59 else { result += *next++; }
60 }
61 return result;
62 }
uint16_t U16
Definition BasicTypes.h:7
#define INDENT_STRING
Definition Print.cpp:13
#define DEDENT_STRING
Definition Print.cpp:14
uint32_t next(octet_iterator &it, octet_iterator end)
Definition checked.h:137
Here is the caller graph for this function:

◆ findClosingParenthesis()

void WAST::findClosingParenthesis ( ParseState & state,
const Token * openingParenthesisToken )

Definition at line 19 of file Parse.cpp.

20 {
21 // Skip over tokens until the ')' closing the current parentheses nesting depth is found.
22 Uptr depth = 1;
23 while(depth > 0)
24 {
25 switch(state.nextToken->type)
26 {
27 default:
28 ++state.nextToken;
29 break;
30 case t_leftParenthesis:
31 ++state.nextToken;
32 ++depth;
33 break;
34 case t_rightParenthesis:
35 ++state.nextToken;
36 --depth;
37 break;
38 case t_eof:
39 parseErrorf(state,openingParenthesisToken,"reached end of input while trying to find closing parenthesis");
40 throw FatalParseException();
41 }
42 }
43 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ freeLineInfo()

void WAST::freeLineInfo ( LineInfo * lineInfo)

Definition at line 319 of file Lexer.cpp.

320 {
321 free(lineInfo->lineStarts);
322 delete lineInfo;
323 }
Here is the caller graph for this function:

◆ freeTokens()

void WAST::freeTokens ( Token * tokens)

Definition at line 314 of file Lexer.cpp.

315 {
316 free(tokens);
317 }
Here is the caller graph for this function:

◆ getUniqueFunctionTypeIndex()

IR::IndexedFunctionType WAST::getUniqueFunctionTypeIndex ( ModuleParseState & state,
const FunctionType * functionType )

Definition at line 226 of file Parse.cpp.

227 {
228 // If this type is not in the module's type table yet, add it.
229 auto functionTypeToIndexMapIt = state.functionTypeToIndexMap.find(functionType);
230 if(functionTypeToIndexMapIt != state.functionTypeToIndexMap.end())
231 {
232 return IndexedFunctionType {functionTypeToIndexMapIt->second};
233 }
234 else
235 {
236 const Uptr functionTypeIndex = state.module.types.size();
237 state.module.types.push_back(functionType);
238 state.disassemblyNames.types.push_back(std::string());
239 errorUnless(functionTypeIndex < UINT32_MAX);
240 state.functionTypeToIndexMap.emplace(functionType,(U32)functionTypeIndex);
241 return IndexedFunctionType {(U32)functionTypeIndex};
242 }
243 }
Here is the caller graph for this function:

◆ isRecoveryPointChar()

bool WAST::isRecoveryPointChar ( char c)
inline

Definition at line 153 of file Lexer.cpp.

154 {
155 switch(c)
156 {
157 // Recover lexing at the next whitespace or parenthesis.
158 case ' ': case '\t': case '\r': case '\n': case '\f':
159 case '(': case ')':
160 return true;
161 default:
162 return false;
163 };
164 }
Here is the caller graph for this function:

◆ lex()

Token * WAST::lex ( const char * string,
Uptr stringLength,
LineInfo *& outLineInfo )

Definition at line 166 of file Lexer.cpp.

167 {
168 static StaticData staticData;
169
170 Timing::Timer timer;
171
172 if(stringLength > UINT32_MAX)
173 {
174 Errors::fatalf("cannot lex strings with more than %u characters",UINT32_MAX);
175 }
176
177 // Allocate enough memory up front for a token and newline for each character in the input string.
178 Token* tokens = (Token*)malloc(sizeof(Token) * (stringLength + 1));
179 U32* lineStarts = (U32*)malloc(sizeof(U32) * (stringLength + 2));
180
181 Token* nextToken = tokens;
182 U32* nextLineStart = lineStarts;
183 *nextLineStart++ = 0;
184
185 const char* nextChar = string;
186 while(true)
187 {
188 // Skip whitespace and comments (keeping track of newlines).
189 while(true)
190 {
191 switch(*nextChar)
192 {
193 // Single line comments.
194 case ';':
195 if(nextChar[1] != ';') { goto doneSkippingWhitespace; }
196 else
197 {
198 nextChar += 2;
199 while(*nextChar)
200 {
201 if(*nextChar == '\n')
202 {
203 // Emit a line start for the newline.
204 *nextLineStart++ = U32(nextChar - string + 1);
205 ++nextChar;
206 break;
207 }
208 ++nextChar;
209 };
210 }
211 break;
212 // Delimited (possibly multi-line) comments.
213 case '(':
214 if(nextChar[1] != ';') { goto doneSkippingWhitespace; }
215 else
216 {
217 const char* firstCommentChar = nextChar;
218 nextChar += 2;
219 U32 commentDepth = 1;
220 while(commentDepth)
221 {
222 if(nextChar[0] == ';' && nextChar[1] == ')')
223 {
224 --commentDepth;
225 nextChar += 2;
226 }
227 else if(nextChar[0] == '(' && nextChar[1] == ';')
228 {
229 ++commentDepth;
230 nextChar += 2;
231 }
232 else if(nextChar == string + stringLength)
233 {
234 // Emit an unterminated comment token.
235 nextToken->type = t_unterminatedComment;
236 nextToken->begin = U32(firstCommentChar - string);
237 ++nextToken;
238 goto doneSkippingWhitespace;
239 }
240 else
241 {
242 if(*nextChar == '\n')
243 {
244 // Emit a line start for the newline.
245 *nextLineStart++ = U32(nextChar - string);
246 }
247 ++nextChar;
248 }
249 };
250 }
251 break;
252 // Whitespace.
253 case '\n':
254 *nextLineStart++ = U32(nextChar - string + 1);
255 ++nextChar;
256 break;
257 case ' ': case '\t': case '\r': case '\f':
258 ++nextChar;
259 break;
260 default:
261 goto doneSkippingWhitespace;
262 };
263 }
264 doneSkippingWhitespace:
265
266 // Once we reach a non-whitespace, non-comment character, feed characters into the NFA until it reaches a terminal state.
267 nextToken->begin = U32(nextChar - string);
268 NFA::StateIndex terminalState = staticData.nfaMachine.feed(nextChar);
269 if(terminalState != NFA::unmatchedCharacterTerminal)
270 {
271 nextToken->type = TokenType(NFA::maximumTerminalStateIndex - (NFA::StateIndex)terminalState);
272 ++nextToken;
273 }
274 else
275 {
276 if(nextToken->begin < stringLength)
277 {
278 // Emit an unrecognized token.
279 nextToken->type = t_unrecognized;
280 ++nextToken;
281
282 // Advance until a recovery point.
283 while(!isRecoveryPointChar(*nextChar)) { ++nextChar; }
284 }
285 else
286 {
287 break;
288 }
289 }
290 }
291
292 // Emit an end token to mark the end of the token stream.
293 nextToken->type = t_eof;
294 ++nextToken;
295
296 // Emit an extra line start for the end of the file, so you can find the end of a line with lineStarts[line + 1].
297 *nextLineStart++ = U32(nextChar - string) + 1;
298
299 // Shrink the line start and token arrays to the final number of tokens/lines.
300 const Uptr numLineStarts = nextLineStart - lineStarts;
301 const Uptr numTokens = nextToken - tokens;
302 lineStarts = (U32*)realloc(lineStarts,sizeof(U32) * numLineStarts);
303 tokens = (Token*)realloc(tokens,sizeof(Token) * numTokens);
304
305 // Create the LineInfo object that encapsulates the line start information.
306 outLineInfo = new LineInfo {lineStarts,U32(numLineStarts)};
307
308 Timing::logRatePerSecond("lexed WAST file",timer,stringLength/1024.0/1024.0,"MB");
309 Log::printf(Log::Category::metrics,"lexer produced %u tokens (%.1fMB)\n",numTokens,numTokens*sizeof(Token)/1024.0/1024.0);
310
311 return tokens;
312 }
void fatalf(const char *messageFormat,...)
Definition Errors.h:12
LOGGING_API void printf(Category category, const char *format,...)
Definition Logging.cpp:30
@ maximumTerminalStateIndex
Definition NFA.h:20
@ unmatchedCharacterTerminal
Definition NFA.h:19
I16 StateIndex
Definition NFA.h:14
void logRatePerSecond(const char *context, Timer &timer, F64 numerator, const char *numeratorUnit)
Definition Timing.h:29
bool isRecoveryPointChar(char c)
Definition Lexer.cpp:153
StateIndex feed(const char *&nextChar) const
Definition NFA.h:51
NFA::Machine nfaMachine
Definition Lexer.cpp:29
Here is the call graph for this function:
Here is the caller graph for this function:

◆ nibbleToHexChar()

char WAST::nibbleToHexChar ( U8 value)

Definition at line 16 of file Print.cpp.

16{ return value < 10 ? ('0' + value) : 'a' + value - 10; }
#define value
Definition pkcs11.h:157
Here is the caller graph for this function:

◆ PACKED_STRUCT()

WAST::PACKED_STRUCT ( struct Token { TokenType type;U32 begin;} )

◆ parseAndResolveNameOrIndexRef()

U32 WAST::parseAndResolveNameOrIndexRef ( ParseState & state,
const NameToIndexMap & nameToIndexMap,
Uptr maxIndex,
const char * context )

Definition at line 295 of file Parse.cpp.

296 {
297 Reference ref;
298
299 if(strcmp(context, "type") == 0 //limits this block strictly to call_indirect
300 && state.nextToken[0].type == t_leftParenthesis
301 && state.nextToken[1].type == t_type)
302 {
303 parseParenthesized(state,[&]
304 {
305 require(state,t_type);
307 {
308 parseErrorf(state,state.nextToken,"expected type name or index");
309 throw RecoverParseException();
310 }
311 });
312 }
313
314 if(ref.type == Reference::Type::invalid && !tryParseNameOrIndexRef(state,ref))
315 {
316 parseErrorf(state,state.nextToken,"expected %s name or index",context);
317 throw RecoverParseException();
318 }
319 return resolveRef(state,nameToIndexMap,maxIndex,ref);
320 }
void require(ParseState &state, TokenType type)
Definition Parse.cpp:78
bool tryParseNameOrIndexRef(ParseState &state, Reference &outRef)
Definition Parse.cpp:287
U32 resolveRef(ParseState &state, const NameToIndexMap &nameToIndexMap, Uptr maxIndex, const Reference &ref)
Definition Parse.cpp:338
Here is the call graph for this function:

◆ parseErrorf() [1/4]

void WAST::parseErrorf ( ParseState & state,
const char * nextChar,
const char * messageFormat,
... )

Definition at line 63 of file Parse.cpp.

64 {
65 va_list messageArguments;
66 va_start(messageArguments,messageFormat);
67 parseErrorf(state,nextChar - state.string,messageFormat,messageArguments);
68 va_end(messageArguments);
69 }
Here is the call graph for this function:

◆ parseErrorf() [2/4]

void WAST::parseErrorf ( ParseState & state,
const Token * nextToken,
const char * messageFormat,
... )

Definition at line 70 of file Parse.cpp.

71 {
72 va_list messageArguments;
73 va_start(messageArguments,messageFormat);
74 parseErrorf(state,nextToken->begin,messageFormat,messageArguments);
75 va_end(messageArguments);
76 }
Here is the call graph for this function:

◆ parseErrorf() [3/4]

void WAST::parseErrorf ( ParseState & state,
Uptr charOffset,
const char * messageFormat,
va_list messageArguments )

Definition at line 45 of file Parse.cpp.

46 {
47 // Format the message.
48 char messageBuffer[1024];
49 int numPrintedChars = std::vsnprintf(messageBuffer,sizeof(messageBuffer),messageFormat,messageArguments);
50 if(numPrintedChars >= 1023 || numPrintedChars < 0) { Errors::unreachable(); }
51 messageBuffer[numPrintedChars] = 0;
52
53 // Add the error to the state's error list.
54 state.errors.emplace_back(charOffset,messageBuffer);
55 }
void unreachable()
Definition Errors.h:22
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseErrorf() [4/4]

void WAST::parseErrorf ( ParseState & state,
Uptr charOffset,
const char * messageFormat,
... )

Definition at line 56 of file Parse.cpp.

57 {
58 va_list messageArguments;
59 va_start(messageArguments,messageFormat);
60 parseErrorf(state,charOffset,messageFormat,messageArguments);
61 va_end(messageArguments);
62 }
Here is the call graph for this function:

◆ parseF32()

F32 WAST::parseF32 ( ParseState & state)

Definition at line 320 of file ParseNumbers.cpp.

321 {
322 F32 result;
323 if(!tryParseFloat(state,result))
324 {
325 parseErrorf(state,state.nextToken,"expected f32 literal");
326 throw RecoverParseException();
327 }
328 return result;
329 }
float F32
Definition BasicTypes.h:13
bool tryParseFloat(ParseState &state, Float &outFloat)
Here is the call graph for this function:

◆ parseF64()

F64 WAST::parseF64 ( ParseState & state)

Definition at line 331 of file ParseNumbers.cpp.

332 {
333 F64 result;
334 if(!tryParseFloat(state,result))
335 {
336 parseErrorf(state,state.nextToken,"expected f64 literal");
337 throw RecoverParseException();
338 }
339 return result;
340 }
double F64
Definition BasicTypes.h:14
Here is the call graph for this function:

◆ parseFunctionDef()

FunctionDef WAST::parseFunctionDef ( ModuleParseState & state,
const Token * funcToken )

Definition at line 542 of file ParseFunction.cpp.

543 {
544 std::vector<std::string>* localDisassemblyNames = new std::vector<std::string>;
545 NameToIndexMap* localNameToIndexMap = new NameToIndexMap();
546
547 // Parse the function type, as a reference or explicit declaration.
548 const UnresolvedFunctionType unresolvedFunctionType = parseFunctionTypeRefAndOrDecl(state,*localNameToIndexMap,*localDisassemblyNames);
549
550 // Defer resolving the function type until all type declarations have been parsed.
551 const Uptr functionIndex = state.module.functions.size();
552 const Uptr functionDefIndex = state.module.functions.defs.size();
553 const Token* firstBodyToken = state.nextToken;
554 state.postTypeCallbacks.push_back(
555 [functionIndex,functionDefIndex,firstBodyToken,localNameToIndexMap,localDisassemblyNames,unresolvedFunctionType]
557 {
558 // Resolve the function type and set it on the FunctionDef.
559 const IndexedFunctionType functionTypeIndex = resolveFunctionType(state,unresolvedFunctionType);
560 state.module.functions.defs[functionDefIndex].type = functionTypeIndex;
561
562 // Defer parsing the body of the function until all function types have been resolved.
563 state.postDeclarationCallbacks.push_back(
564 [functionIndex,functionDefIndex,firstBodyToken,localNameToIndexMap,localDisassemblyNames,functionTypeIndex]
566 {
567 FunctionDef& functionDef = state.module.functions.defs[functionDefIndex];
568 const FunctionType* functionType = functionTypeIndex.index == UINT32_MAX
570 : state.module.types[functionTypeIndex.index];
571
572 // Parse the function's local variables.
573 ParseState localParseState(state.string,state.lineInfo,state.errors,firstBodyToken);
574 while(tryParseParenthesizedTagged(localParseState,t_local,[&]
575 {
576 Name localName;
577 if(tryParseName(localParseState,localName))
578 {
579 bindName(localParseState,*localNameToIndexMap,localName,functionType->parameters.size() + functionDef.nonParameterLocalTypes.size());
580 localDisassemblyNames->push_back(localName.getString());
581 functionDef.nonParameterLocalTypes.push_back(parseValueType(localParseState));
582 }
583 else
584 {
585 while(localParseState.nextToken->type != t_rightParenthesis)
586 {
587 localDisassemblyNames->push_back(std::string());
588 functionDef.nonParameterLocalTypes.push_back(parseValueType(localParseState));
589 };
590 }
591 }));
592 state.disassemblyNames.functions[functionIndex].locals = std::move(*localDisassemblyNames);
593 delete localDisassemblyNames;
594
595 // Parse the function's code.
596 FunctionParseState functionState(state,localNameToIndexMap,localParseState.nextToken,functionDef);
597 try
598 {
599 parseInstrSequence(functionState);
600 if(!functionState.errors.size())
601 {
602 functionState.validatingCodeStream.end();
603 functionState.validatingCodeStream.finishValidation();
604 }
605 }
606 catch(ValidationException exception)
607 {
608 parseErrorf(state,firstBodyToken,"%s",exception.message.c_str());
609 }
610 catch(RecoverParseException) {}
611 catch(FatalParseException) {}
612 functionDef.code = std::move(functionState.codeByteStream.getBytes());
613 });
614 });
615
616 // Continue parsing after the closing parenthesis.
617 findClosingParenthesis(state,funcToken-1);
618 --state.nextToken;
619
620 return {{UINT32_MAX},{},{}};
621 }
std::unordered_map< Name, U32, Name::Hasher > NameToIndexMap
Definition Parse.h:88
bool tryParseName(ParseState &state, Name &outName)
Definition Parse.cpp:252
void findClosingParenthesis(ParseState &state, const Token *openingParenthesisToken)
Definition Parse.cpp:19
void bindName(ParseState &state, NameToIndexMap &nameToIndexMap, const Name &name, Uptr index)
Definition Parse.cpp:322
UnresolvedFunctionType parseFunctionTypeRefAndOrDecl(ModuleParseState &state, NameToIndexMap &outLocalNameToIndexMap, std::vector< std::string > &outLocalDisassemblyNames)
Definition Parse.cpp:170
IndexedFunctionType resolveFunctionType(ModuleParseState &state, const UnresolvedFunctionType &unresolvedType)
Definition Parse.cpp:197
ValueType parseValueType(ParseState &state)
Definition Parse.cpp:110
std::vector< U8 > code
Definition Module.h:45
std::vector< ValueType > nonParameterLocalTypes
Definition Module.h:44
std::vector< ValueType > parameters
Definition Types.h:196
static IR_API const FunctionType * get(ResultType ret, const std::initializer_list< ValueType > &parameters)
Definition Types.cpp:38
std::string message
Definition Validate.h:15
std::string getString() const
Definition Parse.h:58
Here is the call graph for this function:

◆ parseFunctionType()

const IR::FunctionType * WAST::parseFunctionType ( ModuleParseState & state,
NameToIndexMap & outLocalNameToIndexMap,
std::vector< std::string > & outLocalDisassemblyNames )

Definition at line 121 of file Parse.cpp.

122 {
123 std::vector<ValueType> parameters;
124 ResultType ret = ResultType::none;
125
126 // Parse the function parameters.
127 while(tryParseParenthesizedTagged(state,t_param,[&]
128 {
129 Name parameterName;
130 if(tryParseName(state,parameterName))
131 {
132 // (param <name> <type>)
133 bindName(state,outLocalNameToIndexMap,parameterName,parameters.size());
134 parameters.push_back(parseValueType(state));
135 outLocalDisassemblyNames.push_back(parameterName.getString());
136 }
137 else
138 {
139 // (param <type>*)
140 ValueType parameterType;
141 while(tryParseValueType(state,parameterType))
142 {
143 parameters.push_back(parameterType);
144 outLocalDisassemblyNames.push_back(std::string());
145 };
146 }
147 }));
148
149 // Parse <= 1 result type: (result <value type>*)*
150 while(state.nextToken[0].type == t_leftParenthesis
151 && state.nextToken[1].type == t_result)
152 {
153 parseParenthesized(state,[&]
154 {
155 require(state,t_result);
156
157 ResultType resultElementType;
158 const Token* elementToken = state.nextToken;
159 while(tryParseResultType(state,resultElementType))
160 {
161 if(ret != ResultType::none) { parseErrorf(state,elementToken,"function type cannot have more than 1 result element"); }
162 ret = resultElementType;
163 };
164 });
165 };
166
167 return FunctionType::get(ret,parameters);
168 }
ValueType
Definition Types.h:14
ResultType
Definition Types.h:134
bool tryParseResultType(ParseState &state, ResultType &outResultType)
Definition Parse.cpp:105
CK_RV ret
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseFunctionTypeRefAndOrDecl()

UnresolvedFunctionType WAST::parseFunctionTypeRefAndOrDecl ( ModuleParseState & state,
NameToIndexMap & outLocalNameToIndexMap,
std::vector< std::string > & outLocalDisassemblyNames )

Definition at line 170 of file Parse.cpp.

171 {
172 // Parse an optional function type reference.
173 Reference functionTypeRef;
174 if(state.nextToken[0].type == t_leftParenthesis
175 && state.nextToken[1].type == t_type)
176 {
177 parseParenthesized(state,[&]
178 {
179 require(state,t_type);
180 if(!tryParseNameOrIndexRef(state,functionTypeRef))
181 {
182 parseErrorf(state,state.nextToken,"expected type name or index");
183 throw RecoverParseException();
184 }
185 });
186 }
187
188 // Parse the explicit function parameters and result type.
189 const FunctionType* explicitFunctionType = parseFunctionType(state,outLocalNameToIndexMap,outLocalDisassemblyNames);
190
191 UnresolvedFunctionType result;
192 result.reference = functionTypeRef;
193 result.explicitType = explicitFunctionType;
194 return result;
195 }
const FunctionType * parseFunctionType(ModuleParseState &state, NameToIndexMap &outLocalNameToIndexMap, std::vector< std::string > &outLocalDisassemblyNames)
Definition Parse.cpp:121
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseI32()

U32 WAST::parseI32 ( ParseState & state)

Definition at line 298 of file ParseNumbers.cpp.

299 {
300 U32 result;
301 if(!tryParseI32(state,result))
302 {
303 parseErrorf(state,state.nextToken,"expected i32 literal");
304 throw RecoverParseException();
305 }
306 return result;
307 }
bool tryParseI32(ParseState &state, U32 &outI32)
Here is the call graph for this function:

◆ parseI64()

U64 WAST::parseI64 ( ParseState & state)

Definition at line 309 of file ParseNumbers.cpp.

310 {
311 U64 result;
312 if(!tryParseI64(state,result))
313 {
314 parseErrorf(state,state.nextToken,"expected i64 literal");
315 throw RecoverParseException();
316 }
317 return result;
318 }
uint64_t U64
Definition BasicTypes.h:11
bool tryParseI64(ParseState &state, U64 &outI64)
Here is the call graph for this function:

◆ parseI8()

U8 WAST::parseI8 ( ParseState & state)

Definition at line 287 of file ParseNumbers.cpp.

288 {
289 U32 result;
291 {
292 parseErrorf(state,state.nextToken,"expected i8 literal");
293 throw RecoverParseException();
294 }
295 return U8(result);
296 }
uint8_t U8
Definition BasicTypes.h:5
bool tryParseInt(ParseState &state, UnsignedInt &outUnsignedInt, I64 minSignedValue, U64 maxUnsignedValue)
#define INT8_MIN
Definition stdint.h:178
#define UINT8_MAX
Definition stdint.h:186
Here is the call graph for this function:

◆ parseModule()

bool WAST::parseModule ( const char * string,
Uptr stringLength,
IR::Module & outModule,
std::vector< Error > & outErrors )

Definition at line 638 of file ParseModule.cpp.

639 {
640 Timing::Timer timer;
641
642 // Lex the string.
643 LineInfo* lineInfo = nullptr;
644 std::vector<UnresolvedError> unresolvedErrors;
645 Token* tokens = lex(string,stringLength,lineInfo);
646 ModuleParseState state(string,lineInfo,unresolvedErrors,tokens,outModule);
647
648 try
649 {
650 // Parse (module ...)<eof>
651 parseParenthesized(state,[&]
652 {
653 require(state,t_module);
655 });
656 require(state,t_eof);
657 }
658 catch(RecoverParseException) {}
659 catch(FatalParseException) {}
660
661 // Resolve line information for any errors, and write them to outErrors.
662 for(auto& unresolvedError : unresolvedErrors)
663 {
664 TextFileLocus locus = calcLocusFromOffset(state.string,lineInfo,unresolvedError.charOffset);
665 outErrors.push_back({std::move(locus),std::move(unresolvedError.message)});
666 }
667
668 // Free the tokens and line info.
669 freeTokens(tokens);
670 freeLineInfo(lineInfo);
671
672 Timing::logRatePerSecond("lexed and parsed WAST",timer,stringLength / 1024.0 / 1024.0,"MB");
673
674 return outErrors.size() == 0;
675 }
Token * lex(const char *string, Uptr stringLength, LineInfo *&outLineInfo)
Definition Lexer.cpp:166
void freeTokens(Token *tokens)
Definition Lexer.cpp:314
void parseModuleBody(ModuleParseState &state)
void freeLineInfo(LineInfo *lineInfo)
Definition Lexer.cpp:319
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseModuleBody()

void WAST::parseModuleBody ( ModuleParseState & state)

Definition at line 589 of file ParseModule.cpp.

590 {
591 const Token* firstToken = state.nextToken;
592
593 // Parse the module's declarations.
594 while(state.nextToken->type != t_rightParenthesis)
595 {
596 parseDeclaration(state);
597 };
598
599 // Process the callbacks requested after all type declarations have been parsed.
600 if(!state.errors.size())
601 {
602 for(const auto& callback : state.postTypeCallbacks)
603 {
604 callback(state);
605 }
606 }
607
608 // Process the callbacks requested after all declarations have been parsed.
609 if(!state.errors.size())
610 {
611 for(const auto& callback : state.postDeclarationCallbacks)
612 {
613 callback(state);
614 }
615 }
616
617 // Validate the module's definitions (excluding function code, which is validated as it is parsed).
618 if(!state.errors.size())
619 {
620 try
621 {
623 }
624 catch(ValidationException validationException)
625 {
626 parseErrorf(state,firstToken,"validation exception: %s",validationException.message.c_str());
627 }
628 }
629
630 // Set the module's disassembly names.
631 WAVM_ASSERT_THROW(state.module.functions.size() == state.disassemblyNames.functions.size());
632 WAVM_ASSERT_THROW(state.module.tables.size() == state.disassemblyNames.tables.size());
633 WAVM_ASSERT_THROW(state.module.memories.size() == state.disassemblyNames.memories.size());
634 WAVM_ASSERT_THROW(state.module.globals.size() == state.disassemblyNames.globals.size());
635 IR::setDisassemblyNames(state.module,state.disassemblyNames);
636 }
IR_API void validateDefinitions(const IR::Module &module)
Definition Validate.cpp:556
IR_API void setDisassemblyNames(Module &module, const DisassemblyNames &names)
Here is the call graph for this function:
Here is the caller graph for this function:

◆ parseTestCommands()

WAST_API void WAST::parseTestCommands ( const char * string,
Uptr stringLength,
std::vector< std::unique_ptr< Command > > & outTestCommands,
std::vector< Error > & outErrors )

◆ parseUTF8String()

std::string WAST::parseUTF8String ( ParseState & state)

Definition at line 481 of file Parse.cpp.

482 {
483 const Token* stringToken = state.nextToken;
484 std::string result;
485 if(!tryParseString(state,result))
486 {
487 parseErrorf(state,stringToken,"expected string literal");
488 throw RecoverParseException();
489 }
490
491 // Check that the string is a valid UTF-8 encoding.
492 const U8* endChar = (const U8*)result.data() + result.size();
493 const U8* nextChar = UTF8::validateString((const U8*)result.data(),endChar);
494 if(nextChar != endChar)
495 {
496 const Uptr charOffset = stringToken->begin + (nextChar - (const U8*)result.data()) + 1;
497 parseErrorf(state,charOffset,"invalid UTF-8 encoding");
498 }
499
500 return result;
501 }
const U8 * validateString(const U8 *nextChar, const U8 *endChar)
Definition UTF8.h:8
bool tryParseString(ParseState &state, std::string &outString)
Definition Parse.cpp:448
Here is the call graph for this function:

◆ parseValueType()

IR::ValueType WAST::parseValueType ( ParseState & state)

Definition at line 110 of file Parse.cpp.

111 {
112 ValueType result;
113 if(!tryParseValueType(state,result))
114 {
115 parseErrorf(state,state.nextToken,"expected value type");
116 throw RecoverParseException();
117 }
118 return result;
119 }
bool tryParseValueType(ParseState &state, ValueType &outValueType)
Definition Parse.cpp:88
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print() [1/8]

std::string WAST::print ( const IR::Module & module)

Definition at line 687 of file Print.cpp.

688 {
689 std::string string;
691 context.printModule();
692 return expandIndentation(std::move(string));
693 }
std::string expandIndentation(std::string &&inString, U8 spacesPerIndentLevel=2)
Definition Print.cpp:38
sysio::client::http::http_context context
Definition main.cpp:200
Here is the call graph for this function:
Here is the caller graph for this function:

◆ print() [2/8]

void WAST::print ( std::string & string,
const FunctionType * functionType )

Definition at line 91 of file Print.cpp.

92 {
93 // Print the function parameters.
94 if(functionType->parameters.size())
95 {
96 ScopedTagPrinter paramTag(string,"param");
97 for(Uptr parameterIndex = 0;parameterIndex < functionType->parameters.size();++parameterIndex)
98 {
99 string += ' ';
100 print(string,functionType->parameters[parameterIndex]);
101 }
102 }
103
104 // Print the function return type.
105 if(functionType->ret != ResultType::none)
106 {
107 string += ' ';
108 ScopedTagPrinter resultTag(string,"result");
109 string += ' ';
110 print(string,functionType->ret);
111 }
112 }
void print(std::ostream &os, int const level, std::string const &title, Catch::SourceLineInfo const &info)
ResultType ret
Definition Types.h:195
Here is the call graph for this function:

◆ print() [3/8]

void WAST::print ( std::string & string,
const MemoryType & type )

Definition at line 120 of file Print.cpp.

121 {
122 print(string,type.size);
123 }
Here is the call graph for this function:

◆ print() [4/8]

void WAST::print ( std::string & string,
const SizeConstraints & size )

Definition at line 85 of file Print.cpp.

86 {
87 string += std::to_string(size.min);
88 if(size.max != UINT64_MAX) { string += ' '; string += std::to_string(size.max); }
89 }
#define UINT64_MAX
Definition stdint.h:189

◆ print() [5/8]

void WAST::print ( std::string & string,
const TableType & type )

Definition at line 114 of file Print.cpp.

115 {
116 print(string,type.size);
117 string += " anyfunc";
118 }
Here is the call graph for this function:

◆ print() [6/8]

void WAST::print ( std::string & string,
GlobalType type )

Definition at line 125 of file Print.cpp.

126 {
127 if(type.isMutable) { string += "(mut "; }
128 print(string,type.valueType);
129 if(type.isMutable) { string += ")"; }
130 }
Here is the call graph for this function:

◆ print() [7/8]

void WAST::print ( std::string & string,
ResultType type )

Definition at line 83 of file Print.cpp.

83{ string += asString(type); }
std::string asString(I32 value)
Definition Types.h:50
Here is the call graph for this function:

◆ print() [8/8]

void WAST::print ( std::string & string,
ValueType type )

Definition at line 82 of file Print.cpp.

82{ string += asString(type); }
Here is the call graph for this function:

◆ printControlSignature()

void WAST::printControlSignature ( std::string & string,
ResultType resultType )

Definition at line 132 of file Print.cpp.

133 {
134 if(resultType != ResultType::none)
135 {
136 string += " (result ";
137 print(string,resultType);
138 string += ')';
139 }
140 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printImport()

template<typename Type >
void WAST::printImport ( std::string & string,
const Module & module,
const Import< Type > & import,
Uptr importIndex,
const char * name,
const char * typeTag )

Definition at line 460 of file Print.cpp.

461 {
462 string += '\n';
463 ScopedTagPrinter importTag(string,"import");
464 string += " \"";
465 string += escapeString(import.moduleName.c_str(),import.moduleName.length());
466 string += "\" \"";
467 string += escapeString(import.exportName.c_str(),import.exportName.length());
468 string += "\" (";
469 string += typeTag;
470 string += ' ';
471 string += name;
472 string += ' ';
473 printImportType(string,module,import.type);
474 string += ')';
475 }
void printImportType(std::string &string, const Module &module, Type type)
Definition Print.cpp:449
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printImportType()

template<typename Type >
void WAST::printImportType ( std::string & string,
const Module & module,
Type type )

Definition at line 449 of file Print.cpp.

450 {
451 print(string,type);
452 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ printImportType< IndexedFunctionType >()

template<>
void WAST::printImportType< IndexedFunctionType > ( std::string & string,
const Module & module,
IndexedFunctionType type )

Definition at line 454 of file Print.cpp.

455 {
456 print(string,module.types[type.index]);
457 }
Here is the call graph for this function:

◆ require()

void WAST::require ( ParseState & state,
TokenType type )

Definition at line 78 of file Parse.cpp.

79 {
80 if(state.nextToken->type != type)
81 {
82 parseErrorf(state,state.nextToken,"expected %s",describeToken(type));
84 }
85 ++state.nextToken;
86 }
const char * describeToken(TokenType tokenType)
Definition Lexer.cpp:14
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveFunctionType()

IR::IndexedFunctionType WAST::resolveFunctionType ( ModuleParseState & state,
const UnresolvedFunctionType & unresolvedType )

Definition at line 197 of file Parse.cpp.

198 {
199 if(!unresolvedType.reference)
200 {
201 return getUniqueFunctionTypeIndex(state,unresolvedType.explicitType);
202 }
203 else
204 {
205 // Resolve the referenced type.
206 const U32 referencedFunctionTypeIndex = resolveRef(state,state.typeNameToIndexMap,state.module.types.size(),unresolvedType.reference);
207
208 // Validate that if the function definition has both a type reference and explicit parameter/result type declarations, they match.
209 const bool hasExplicitParametersOrResultType = unresolvedType.explicitType != FunctionType::get();
210 if(hasExplicitParametersOrResultType)
211 {
212 if(referencedFunctionTypeIndex != UINT32_MAX
213 && state.module.types[referencedFunctionTypeIndex] != unresolvedType.explicitType)
214 {
215 parseErrorf(state,unresolvedType.reference.token,"referenced function type (%s) does not match declared parameters and results (%s)",
216 asString(state.module.types[referencedFunctionTypeIndex]).c_str(),
217 asString(unresolvedType.explicitType).c_str()
218 );
219 }
220 }
221
222 return {referencedFunctionTypeIndex};
223 }
224 }
IndexedFunctionType getUniqueFunctionTypeIndex(ModuleParseState &state, const FunctionType *functionType)
Definition Parse.cpp:226
const Token * token
Definition Parse.h:100
const IR::FunctionType * explicitType
Definition Parse.h:111
Here is the call graph for this function:
Here is the caller graph for this function:

◆ resolveRef()

U32 WAST::resolveRef ( ParseState & state,
const NameToIndexMap & nameToIndexMap,
Uptr maxIndex,
const Reference & ref )

Definition at line 338 of file Parse.cpp.

339 {
340 switch(ref.type)
341 {
342 case Reference::Type::index:
343 {
344 if(ref.index >= maxIndex)
345 {
346 parseErrorf(state,ref.token,"invalid index");
347 return UINT32_MAX;
348 }
349 return ref.index;
350 }
351 case Reference::Type::name:
352 {
353 auto nameToIndexMapIt = nameToIndexMap.find(ref.name);
354 if(nameToIndexMapIt == nameToIndexMap.end())
355 {
356 parseErrorf(state,ref.token,"unknown name");
357 return UINT32_MAX;
358 }
359 else
360 {
361 return nameToIndexMapIt->second;
362 }
363 }
364 default: Errors::unreachable();
365 };
366 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryParseHexit()

bool WAST::tryParseHexit ( const char *& nextChar,
U8 & outValue )

Definition at line 368 of file Parse.cpp.

369 {
370 if(*nextChar >= '0' && *nextChar <= '9') { outValue = *nextChar - '0'; }
371 else if(*nextChar >= 'a' && *nextChar <= 'f') { outValue = *nextChar - 'a' + 10; }
372 else if(*nextChar >= 'A' && *nextChar <= 'F') { outValue = *nextChar - 'A' + 10; }
373 else
374 {
375 outValue = 0;
376 return false;
377 }
378 ++nextChar;
379 return true;
380 }

◆ tryParseI32()

bool WAST::tryParseI32 ( ParseState & state,
U32 & outI32 )

Definition at line 277 of file ParseNumbers.cpp.

278 {
280 }
#define INT32_MIN
Definition stdint.h:182
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryParseI64()

bool WAST::tryParseI64 ( ParseState & state,
U64 & outI64 )

Definition at line 282 of file ParseNumbers.cpp.

283 {
285 }
#define INT64_MIN
Definition stdint.h:184
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryParseName()

bool WAST::tryParseName ( ParseState & state,
Name & outName )

Definition at line 252 of file Parse.cpp.

253 {
254 if(state.nextToken->type != t_name) { return false; }
255
256 // Find the first non-name character.
257 const char* firstChar = state.string + state.nextToken->begin;;
258 const char* nextChar = firstChar;
259 WAVM_ASSERT_THROW(*nextChar == '$');
260 ++nextChar;
261 while(true)
262 {
263 const char c = *nextChar;
264 if((c >= 'a' && c <= 'z')
265 || (c >= 'A' && c <= 'Z')
266 || (c >= '0' && c <= '9')
267 || c=='_' || c=='\'' || c=='+' || c=='-' || c=='*' || c=='/' || c=='\\' || c=='^' || c=='~' || c=='='
268 || c=='<' || c=='>' || c=='!' || c=='?' || c=='@' || c=='#' || c=='$' || c=='%' || c=='&' || c=='|'
269 || c==':' || c=='`' || c=='.')
270 {
271 ++nextChar;
272 }
273 else
274 {
275 break;
276 }
277 };
278
279 WAVM_ASSERT_THROW(U32(nextChar - state.string) > state.nextToken->begin + 1);
280 ++state.nextToken;
281 WAVM_ASSERT_THROW(U32(nextChar - state.string) <= state.nextToken->begin);
282 WAVM_ASSERT_THROW(U32(nextChar - firstChar) <= UINT32_MAX);
283 outName = Name(firstChar,U32(nextChar - firstChar));
284 return true;
285 }
Here is the caller graph for this function:

◆ tryParseNameOrIndexRef()

bool WAST::tryParseNameOrIndexRef ( ParseState & state,
Reference & outRef )

Definition at line 287 of file Parse.cpp.

288 {
289 outRef.token = state.nextToken;
290 if(tryParseName(state,outRef.name)) { outRef.type = Reference::Type::name; return true; }
291 else if(tryParseI32(state,outRef.index)) { outRef.type = Reference::Type::index; return true; }
292 return false;
293 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryParseResultType()

bool WAST::tryParseResultType ( ParseState & state,
ResultType & outResultType )

Definition at line 105 of file Parse.cpp.

106 {
107 return tryParseValueType(state,*(ValueType*)&outResultType);
108 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ tryParseString()

bool WAST::tryParseString ( ParseState & state,
std::string & outString )

Definition at line 448 of file Parse.cpp.

449 {
450 if(state.nextToken->type != t_string)
451 {
452 return false;
453 }
454
455 // Parse a string literal; the lexer has already rejected unterminated strings,
456 // so this just needs to copy the characters and evaluate escape codes.
457 const char* nextChar = state.string + state.nextToken->begin;
458 WAVM_ASSERT_THROW(*nextChar == '\"');
459 ++nextChar;
460 while(true)
461 {
462 switch(*nextChar)
463 {
464 case '\\':
465 {
466 ++nextChar;
467 parseCharEscapeCode(nextChar,state,outString);
468 break;
469 }
470 case '\"':
471 ++state.nextToken;
472 WAVM_ASSERT_THROW(state.string + state.nextToken->begin > nextChar);
473 return true;
474 default:
475 outString += *nextChar++;
476 break;
477 };
478 };
479 }
Here is the caller graph for this function:

◆ tryParseValueType()

bool WAST::tryParseValueType ( ParseState & state,
ValueType & outValueType )

Definition at line 88 of file Parse.cpp.

89 {
90 switch(state.nextToken->type)
91 {
92 case t_i32: ++state.nextToken; outValueType = ValueType::i32; return true;
93 case t_i64: ++state.nextToken; outValueType = ValueType::i64; return true;
94 case t_f32: ++state.nextToken; outValueType = ValueType::f32; return true;
95 case t_f64: ++state.nextToken; outValueType = ValueType::f64; return true;
96 #if ENABLE_SIMD_PROTOTYPE
97 case t_v128: ++state.nextToken; outValueType = ValueType::v128; return true;
98 #endif
99 default:
100 outValueType = ValueType::any;
101 return false;
102 };
103 }
Here is the caller graph for this function: