#ifndef wasm_wasm_s_parser_h
#define wasm_wasm_s_parser_h
#include "mixed_arena.h"
#include "parsing.h"
#include "wasm-builder.h"
#include "wasm.h"
namespace wasm {
class SourceLocation {
public:
cashew::IString filename;
uint32_t line;
uint32_t column;
SourceLocation(cashew::IString filename_,
uint32_t line_,
uint32_t column_ = 0)
: filename(filename_), line(line_), column(column_) {}
};
class Element {
typedef ArenaVector<Element*> List;
bool isList_ = true;
List list_;
cashew::IString str_;
bool dollared_;
bool quoted_;
public:
Element(MixedArena& allocator) : list_(allocator) {}
bool isList() const { return isList_; }
bool isStr() const { return !isList_; }
bool dollared() const { return isStr() && dollared_; }
bool quoted() const { return isStr() && quoted_; }
size_t line = -1;
size_t col = -1;
SourceLocation* startLoc = nullptr;
SourceLocation* endLoc = nullptr;
List& list();
Element* operator[](unsigned i);
size_t size() { return list().size(); }
cashew::IString str() const;
const char* c_str() const;
Element* setString(cashew::IString str__, bool dollared__, bool quoted__);
Element* setMetadata(size_t line_, size_t col_, SourceLocation* startLoc_);
friend std::ostream& operator<<(std::ostream& o, Element& e);
void dump();
};
class SExpressionParser {
char* input;
size_t line;
char* lineStart;
SourceLocation* loc = nullptr;
MixedArena allocator;
public:
SExpressionParser(char* input);
Element* root;
private:
Element* parse();
void skipWhitespace();
void parseDebugLocation();
Element* parseString();
};
class SExpressionWasmBuilder {
Module& wasm;
MixedArena& allocator;
IRProfile profile;
std::vector<Signature> signatures;
std::unordered_map<std::string, size_t> signatureIndices;
std::vector<Name> functionNames;
std::vector<Name> globalNames;
std::vector<Name> eventNames;
int functionCounter = 0;
int globalCounter = 0;
int eventCounter = 0;
std::map<Name, Type> functionTypes;
std::unordered_map<cashew::IString, Index> debugInfoFileIndices;
public:
SExpressionWasmBuilder(Module& wasm, Element& module, IRProfile profile);
private:
void preParseFunctionType(Element& s);
bool isImport(Element& curr);
void preParseImports(Element& curr);
void parseModuleElement(Element& curr);
std::unique_ptr<Function> currFunction;
bool brokeToAutoBlock;
UniqueNameMapper nameMapper;
Signature getFunctionSignature(Element& s);
Name getFunctionName(Element& s);
Name getGlobalName(Element& s);
Name getEventName(Element& s);
void parseStart(Element& s) { wasm.addStart(getFunctionName(*s[1])); }
size_t parseFunctionNames(Element& s, Name& name, Name& exportName);
void parseFunction(Element& s, bool preParseImport = false);
Type stringToType(cashew::IString str,
bool allowError = false,
bool prefix = false) {
return stringToType(str.str, allowError, prefix);
}
Type
stringToType(const char* str, bool allowError = false, bool prefix = false);
HeapType stringToHeapType(cashew::IString str, bool prefix = false) {
return stringToHeapType(str.str, prefix);
}
HeapType stringToHeapType(const char* str, bool prefix = false);
Type elementToType(Element& s);
Type stringToLaneType(const char* str);
bool isType(cashew::IString str) {
return stringToType(str, true) != Type::none;
}
public:
Expression* parseExpression(Element* s) { return parseExpression(*s); }
Expression* parseExpression(Element& s);
Module& getModule() { return wasm; }
private:
Expression* makeExpression(Element& s);
Expression* makeUnreachable();
Expression* makeNop();
Expression* makeBinary(Element& s, BinaryOp op);
Expression* makeUnary(Element& s, UnaryOp op);
Expression* makeSelect(Element& s);
Expression* makeDrop(Element& s);
Expression* makeMemorySize(Element& s);
Expression* makeMemoryGrow(Element& s);
Index getLocalIndex(Element& s);
Expression* makeLocalGet(Element& s);
Expression* makeLocalTee(Element& s);
Expression* makeLocalSet(Element& s);
Expression* makeGlobalGet(Element& s);
Expression* makeGlobalSet(Element& s);
Expression* makeBlock(Element& s);
Expression* makeThenOrElse(Element& s);
Expression* makeConst(Element& s, Type type);
Expression* makeLoad(Element& s, Type type, bool isAtomic);
Expression* makeStore(Element& s, Type type, bool isAtomic);
Expression* makeAtomicRMWOrCmpxchg(Element& s, Type type);
Expression*
makeAtomicRMW(Element& s, Type type, uint8_t bytes, const char* extra);
Expression*
makeAtomicCmpxchg(Element& s, Type type, uint8_t bytes, const char* extra);
Expression* makeAtomicWait(Element& s, Type type);
Expression* makeAtomicNotify(Element& s);
Expression* makeAtomicFence(Element& s);
Expression* makeSIMDExtract(Element& s, SIMDExtractOp op, size_t lanes);
Expression* makeSIMDReplace(Element& s, SIMDReplaceOp op, size_t lanes);
Expression* makeSIMDShuffle(Element& s);
Expression* makeSIMDTernary(Element& s, SIMDTernaryOp op);
Expression* makeSIMDShift(Element& s, SIMDShiftOp op);
Expression* makeSIMDLoad(Element& s, SIMDLoadOp op);
Expression* makeMemoryInit(Element& s);
Expression* makeDataDrop(Element& s);
Expression* makeMemoryCopy(Element& s);
Expression* makeMemoryFill(Element& s);
Expression* makePush(Element& s);
Expression* makePop(Element& s);
Expression* makeIf(Element& s);
Expression* makeMaybeBlock(Element& s, size_t i, Type type);
Expression* makeLoop(Element& s);
Expression* makeCall(Element& s, bool isReturn);
Expression* makeCallIndirect(Element& s, bool isReturn);
template<class T>
void parseCallOperands(Element& s, Index i, Index j, T* call) {
while (i < j) {
call->operands.push_back(parseExpression(s[i]));
i++;
}
}
Name getLabel(Element& s);
Expression* makeBreak(Element& s);
Expression* makeBreakTable(Element& s);
Expression* makeReturn(Element& s);
Expression* makeRefNull(Element& s);
Expression* makeRefIsNull(Element& s);
Expression* makeRefFunc(Element& s);
Expression* makeRefEq(Element& s);
Expression* makeTry(Element& s);
Expression* makeTryOrCatchBody(Element& s, Type type, bool isTry);
Expression* makeThrow(Element& s);
Expression* makeRethrow(Element& s);
Expression* makeBrOnExn(Element& s);
Expression* makeTupleMake(Element& s);
Expression* makeTupleExtract(Element& s);
Expression* makeI31New(Element& s);
Expression* makeI31Get(Element& s, bool signed_);
Expression* makeRefTest(Element& s);
Expression* makeRefCast(Element& s);
Expression* makeBrOnCast(Element& s);
Expression* makeRttCanon(Element& s);
Expression* makeRttSub(Element& s);
Expression* makeStructNew(Element& s, bool default_);
Expression* makeStructGet(Element& s);
Expression* makeStructGet(Element& s, bool signed_);
Expression* makeStructSet(Element& s);
Expression* makeArrayNew(Element& s, bool default_);
Expression* makeArrayGet(Element& s);
Expression* makeArrayGet(Element& s, bool signed_);
Expression* makeArraySet(Element& s);
Expression* makeArrayLen(Element& s);
Type parseOptionalResultType(Element& s, Index& i);
Index parseMemoryLimits(Element& s, Index i);
Index parseMemoryIndex(Element& s, Index i);
std::vector<Type> parseParamOrLocal(Element& s);
std::vector<NameType> parseParamOrLocal(Element& s, size_t& localIndex);
std::vector<Type> parseResults(Element& s);
Signature parseTypeRef(Element& s);
size_t parseTypeUse(Element& s,
size_t startPos,
Signature& functionSignature,
std::vector<NameType>& namedParams);
size_t
parseTypeUse(Element& s, size_t startPos, Signature& functionSignature);
void stringToBinary(const char* input, size_t size, std::vector<char>& data);
void parseMemory(Element& s, bool preParseImport = false);
void parseData(Element& s);
void parseInnerData(Element& s, Index i, Expression* offset, bool isPassive);
void parseExport(Element& s);
void parseImport(Element& s);
void parseGlobal(Element& s, bool preParseImport = false);
void parseTable(Element& s, bool preParseImport = false);
void parseElem(Element& s);
void parseInnerElem(Element& s, Index i = 1, Expression* offset = nullptr);
void parseType(Element& s);
void parseEvent(Element& s, bool preParseImport = false);
Function::DebugLocation getDebugLocation(const SourceLocation& loc);
};
}
#endif