/* * Copyright 2017 WebAssembly Community Group participants * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "src/c-writer.h" #include #include #include #include #include "src/cast.h" #include "src/common.h" #include "src/ir.h" #include "src/literal.h" #include "src/stream.h" #include "src/string-view.h" #define INDENT_SIZE 2 #define UNIMPLEMENTED(x) printf("unimplemented: %s\n", (x)), abort() namespace wabt { namespace { struct Label { Label(LabelType label_type, const std::string& name, const TypeVector& sig, size_t type_stack_size, bool used = false) : label_type(label_type), name(name), sig(sig), type_stack_size(type_stack_size), used(used) {} bool HasValue() const { return !sig.empty(); } LabelType label_type; const std::string& name; const TypeVector& sig; size_t type_stack_size; bool used = false; }; template struct Name { explicit Name(const std::string& name) : name(name) {} const std::string& name; }; typedef Name<0> LocalName; typedef Name<1> GlobalName; typedef Name<2> ExternalPtr; typedef Name<3> ExternalRef; struct GotoLabel { explicit GotoLabel(const Var& var) : var(var) {} const Var& var; }; struct LabelDecl { explicit LabelDecl(const std::string& name) : name(name) {} std::string name; }; struct GlobalVar { explicit GlobalVar(const Var& var) : var(var) {} const Var& var; }; struct StackVar { explicit StackVar(Index index, Type type = Type::Any) : index(index), type(type) {} Index index; Type type; }; struct TypeEnum { explicit TypeEnum(Type type) : type(type) {} Type type; }; struct SignedType { explicit SignedType(Type type) : type(type) {} Type type; }; struct ResultType { explicit ResultType(const TypeVector& types) : types(types) {} const TypeVector& types; }; struct Newline {}; struct OpenBrace {}; struct CloseBrace {}; int GetShiftMask(Type type) { switch (type) { case Type::I32: return 31; case Type::I64: return 63; default: WABT_UNREACHABLE; return 0; } } class CWriter { public: CWriter(Stream* c_stream, Stream* h_stream, const char* header_name, const WriteCOptions& options) : options_(options), c_stream_(c_stream), h_stream_(h_stream), header_name_(header_name) {} Result WriteModule(const Module&); private: typedef std::set SymbolSet; typedef std::map SymbolMap; typedef std::pair StackTypePair; typedef std::map StackVarSymbolMap; void UseStream(Stream*); void WriteCHeader(); void WriteCSource(); size_t MarkTypeStack() const; void ResetTypeStack(size_t mark); Type StackType(Index) const; void PushType(Type); void PushTypes(const TypeVector&); void DropTypes(size_t count); void PushLabel(LabelType, const std::string& name, const FuncSignature&, bool used = false); const Label* FindLabel(const Var& var); bool IsTopLabelUsed() const; void PopLabel(); static std::string AddressOf(const std::string&); static char MangleType(Type); static std::string MangleTypes(const TypeVector&); static std::string MangleMultivalueTypes(const TypeVector&); static std::string MangleName(string_view); static std::string MangleFuncName(string_view, const TypeVector& param_types, const TypeVector& result_types); static std::string MangleGlobalName(string_view, Type); static std::string LegalizeName(string_view); std::string DefineName(SymbolSet*, string_view); std::string DefineImportName(const std::string& name, string_view module_name, string_view mangled_field_name); std::string DefineGlobalScopeName(const std::string&); std::string DefineLocalScopeName(const std::string&); std::string DefineGlobalVarName(const std::string& name); std::string DefineStackVarName(Index, Type, string_view); void Indent(int size = INDENT_SIZE); void Dedent(int size = INDENT_SIZE); void WriteIndent(); void WriteData(const void* src, size_t size); void Writef(const char* format, ...); template void Write(T&& t, U&& u, Args&&... args) { Write(std::forward(t)); Write(std::forward(u)); Write(std::forward(args)...); } std::string GetGlobalName(const std::string&) const; std::string GetGlobalVarName(const std::string& name) const; void Write() {} void Write(Newline); void Write(OpenBrace); void Write(CloseBrace); void Write(Index); void Write(string_view); void Write(const LocalName&); void Write(const GlobalName&); void Write(const ExternalPtr&); void Write(const ExternalRef&); void Write(Type); void Write(SignedType); void Write(TypeEnum); void Write(const Var&); void Write(const GotoLabel&); void Write(const LabelDecl&); void Write(const GlobalVar&); void Write(const StackVar&); void Write(const ResultType&); void Write(const Const&); void WriteInitExpr(const ExprList&); std::string GenerateHeaderGuard() const; void WriteSourceTop(); void WriteMultivalueTypes(); void WriteSandboxStruct(); void WriteFuncTypes(); void WriteImports(); bool IsFuncStatic(std::string name); std::string GetFuncStaticOrExport(std::string); void WriteFuncDeclarations(bool for_header); void WriteFuncDeclaration(const FuncDeclaration&, const std::string&, bool add_storage_class); void WriteEntryFuncs(); void WriteEntryFunc(const FuncDeclaration&, const std::string&, bool add_storage_class); void WriteImportFuncDeclaration(const FuncDeclaration&, const std::string&); std::string GetMainMemoryName(); void WriteGlobalInitializers(); void WriteGlobals(); void WriteGlobalsExport(); void WriteGlobal(const Global&, const std::string&); void WriteMemories(); void WriteMemoriesExport(); void WriteMemory(const std::string&); void WriteTables(); void WriteTablesExport(); void WriteTable(const std::string&); void WriteDataInitializers(); void WriteElemInitializers(); void WriteExportLookup(); void WriteCallbackAddRemove(); void WriteInit(); void WriteFuncs(); void Write(const Func&); void WriteParamsAndLocals(); void WriteParams(const std::vector& index_to_name); void WriteLocals(const std::vector& index_to_name); void WriteStackVarDeclarations(); void Write(const ExprList&); enum class AssignOp { Disallowed, Allowed, }; void WriteSimpleUnaryExpr(Opcode, const char* op); void WriteInfixBinaryExpr(Opcode, const char* op, AssignOp = AssignOp::Allowed); void WritePrefixBinaryExpr(Opcode, const char* op); void WriteSignedBinaryExpr(Opcode, const char* op); void Write(const BinaryExpr&); void Write(const CompareExpr&); void Write(const ConvertExpr&); void Write(const LoadExpr&); void Write(const StoreExpr&); void Write(const UnaryExpr&); void Write(const TernaryExpr&); void Write(const SimdLaneOpExpr&); void Write(const SimdLoadLaneExpr&); void Write(const SimdStoreLaneExpr&); void Write(const SimdShuffleOpExpr&); void Write(const LoadSplatExpr&); void Write(const LoadZeroExpr&); const WriteCOptions& options_; const Module* module_ = nullptr; const Func* func_ = nullptr; Stream* stream_ = nullptr; MemoryStream func_stream_; Stream* c_stream_ = nullptr; Stream* h_stream_ = nullptr; std::string header_name_; Result result_ = Result::Ok; int indent_ = 0; bool should_write_indent_next_ = false; SymbolMap global_sym_map_; SymbolMap local_sym_map_; SymbolMap globalvars_sym_map_; StackVarSymbolMap stack_var_sym_map_; SymbolSet global_syms_; SymbolSet local_syms_; SymbolSet globalvars_syms_; SymbolSet import_syms_; TypeVector type_stack_; std::vector