diff options
Diffstat (limited to 'src/binaryen-c.cpp')
-rw-r--r-- | src/binaryen-c.cpp | 373 |
1 files changed, 373 insertions, 0 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp new file mode 100644 index 000000000..3ee47e2a9 --- /dev/null +++ b/src/binaryen-c.cpp @@ -0,0 +1,373 @@ +/* + * Copyright 2016 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. + */ + +//=============================== +// Binaryen C API implementation +//=============================== + +#include "binaryen-c.h" +#include "wasm.h" +#include "wasm-builder.h" +#include "wasm-printing.h" + +using namespace wasm; + +// Literal utilities + +static_assert(sizeof(BinaryenLiteral) == sizeof(Literal), "Binaryen C API literal must match wasm.h"); + +BinaryenLiteral toBinaryenLiteral(Literal x) { + BinaryenLiteral ret; + switch (x.type) { + case WasmType::i32: ret.i32 = x.geti32(); break; + case WasmType::i64: ret.i64 = x.geti64(); break; + case WasmType::f32: ret.i32 = x.reinterpreti32(); break; + case WasmType::f64: ret.i64 = x.reinterpreti64(); break; + default: abort(); + } + return ret; +} + +Literal fromBinaryenLiteral(BinaryenLiteral x) { + switch (x.type) { + case WasmType::i32: return Literal(x.i32); + case WasmType::i64: return Literal(x.i64); + case WasmType::f32: return Literal(x.i32).castToF32(); + case WasmType::f64: return Literal(x.i64).castToF64(); + default: abort(); + } +} + +extern "C" { + +// +// ========== Module Creation ========== +// + +// Core types + +BinaryenType BinaryenNone(void) { return none; } +BinaryenType BinaryenInt32(void) { return i32; } +BinaryenType BinaryenInt64(void) { return i64; } +BinaryenType BinaryenFloat32(void) { return f32; } +BinaryenType BinaryenFloat64(void) { return f64; } + +// Modules + +BinaryenModuleRef BinaryenModuleCreate() { return new Module(); } +void BinaryenModuleDispose(BinaryenModuleRef module) { delete (Module*)module; } + +// Function types + +BinaryenFunctionTypeRef BinaryenAddFunctionType(BinaryenModuleRef module, const char* name, BinaryenType result, BinaryenType* paramTypes, BinaryenIndex numParams) { + auto* wasm = (Module*)module; + auto* ret = new FunctionType; + ret->name = name; + ret->result = WasmType(result); + for (BinaryenIndex i = 0; i < numParams; i++) { + ret->params.push_back(WasmType(paramTypes[i])); + } + wasm->addFunctionType(ret); + return ret; +} + +BinaryenLiteral BinaryenLiteralInt32(int32_t x) { return toBinaryenLiteral(Literal(x)); } +BinaryenLiteral BinaryenLiteralInt64(int64_t x) { return toBinaryenLiteral(Literal(x)); } +BinaryenLiteral BinaryenLiteralFloat32(float x) { return toBinaryenLiteral(Literal(x)); } +BinaryenLiteral BinaryenLiteralFloat64(double x) { return toBinaryenLiteral(Literal(x)); } +BinaryenLiteral BinaryenLiteralFloat32Bits(int32_t x) { return toBinaryenLiteral(Literal(x).castToF32()); } +BinaryenLiteral BinaryenLiteralFloat64Bits(int64_t x) { return toBinaryenLiteral(Literal(x).castToF64()); } + +// Expressions + +BinaryenOp BinaryenClz(void) { return Clz; } +BinaryenOp BinaryenCtz(void) { return Ctz; } +BinaryenOp BinaryenPopcnt(void) { return Popcnt; } +BinaryenOp BinaryenNeg(void) { return Neg; } +BinaryenOp BinaryenAbs(void) { return Abs; } +BinaryenOp BinaryenCeil(void) { return Ceil; } +BinaryenOp BinaryenFloor(void) { return Floor; } +BinaryenOp BinaryenTrunc(void) { return Trunc; } +BinaryenOp BinaryenNearest(void) { return Nearest; } +BinaryenOp BinaryenSqrt(void) { return Sqrt; } +BinaryenOp BinaryenEqz(void) { return EqZ; } +BinaryenOp BinaryenExtendSInt32(void) { return ExtendSInt32; } +BinaryenOp BinaryenExtentUInt32(void) { return ExtendUInt32; } +BinaryenOp BinaryenWrapInt64(void) { return WrapInt64; } +BinaryenOp BinaryenTruncSFloat32(void) { return TruncSFloat32; } +BinaryenOp BinaryenTruncUFloat32(void) { return TruncUFloat32; } +BinaryenOp BinaryenTruncSFloat64(void) { return TruncSFloat64; } +BinaryenOp BinaryenTruncUFloat64(void) { return TruncUFloat64; } +BinaryenOp BinaryenReinterpretFloat(void) { return ReinterpretFloat; } +BinaryenOp BinaryenConvertSInt32(void) { return ConvertSInt32; } +BinaryenOp BinaryenConvertUInt32(void) { return ConvertUInt32; } +BinaryenOp BinaryenConvertSInt64(void) { return ConvertSInt64; } +BinaryenOp BinaryenConvertUInt64(void) { return ConvertUInt64; } +BinaryenOp BinaryenPromoteFloat32(void) { return PromoteFloat32; } +BinaryenOp BinaryenDemoteFloat64(void) { return DemoteFloat64; } +BinaryenOp BinaryenReinterpretInt(void) { return ReinterpretInt; } +BinaryenOp BinaryenAdd(void) { return Add; } +BinaryenOp BinaryenSub(void) { return Sub; } +BinaryenOp BinaryenMul(void) { return Mul; } +BinaryenOp BinaryenDivS(void) { return DivS; } +BinaryenOp BinaryenDivU(void) { return DivU; } +BinaryenOp BinaryenRemS(void) { return RemS; } +BinaryenOp BinaryenRemU(void) { return RemU; } +BinaryenOp BinaryenAnd(void) { return And; } +BinaryenOp BinaryenOr(void) { return Or; } +BinaryenOp BinaryenXor(void) { return Xor; } +BinaryenOp BinaryenShl(void) { return Shl; } +BinaryenOp BinaryenShrU(void) { return ShrU; } +BinaryenOp BinaryenShrS(void) { return ShrS; } +BinaryenOp BinaryenRotL(void) { return RotL; } +BinaryenOp BinaryenRotR(void) { return RotR; } +BinaryenOp BinaryenDiv(void) { return Div; } +BinaryenOp BinaryenCopySign(void) { return CopySign; } +BinaryenOp BinaryenMin(void) { return Min; } +BinaryenOp BinaryenMax(void) { return Max; } +BinaryenOp BinaryenEq(void) { return Eq; } +BinaryenOp BinaryenNe(void) { return Ne; } +BinaryenOp BinaryenLtS(void) { return LtS; } +BinaryenOp BinaryenLtU(void) { return LtU; } +BinaryenOp BinaryenLeS(void) { return LeS; } +BinaryenOp BinaryenLeU(void) { return LeU; } +BinaryenOp BinaryenGtS(void) { return GtS; } +BinaryenOp BinaryenGtU(void) { return GtU; } +BinaryenOp BinaryenGes(void) { return GeS; } +BinaryenOp BinaryenGeU(void) { return GeU; } +BinaryenOp BinaryenLt(void) { return Lt; } +BinaryenOp BinaryenLe(void) { return Le; } +BinaryenOp BinaryenGt(void) { return Gt; } +BinaryenOp BinaryenGe(void) { return Ge; } +BinaryenOp BinaryenPageSize(void) { return PageSize; } +BinaryenOp BinaryenCurrentMemory(void) { return CurrentMemory; } +BinaryenOp BinaryenGrowMemory(void) { return GrowMemory; } +BinaryenOp BinaryenHasFeature(void) { return HasFeature; } + +BinaryenExpressionRef BinaryenBlock(BinaryenModuleRef module, const char* name, BinaryenExpressionRef* children, BinaryenIndex numChildren) { + auto* ret = ((Module*)module)->allocator.alloc<Block>(); + if (name) { + ret->name = name; + } + for (BinaryenIndex i = 0; i < numChildren; i++) { + ret->list.push_back((Expression*)children[i]); + } + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenIf(BinaryenModuleRef module, BinaryenExpressionRef condition, BinaryenExpressionRef ifTrue, BinaryenExpressionRef ifFalse) { + auto* ret = ((Module*)module)->allocator.alloc<If>(); + ret->condition = (Expression*)condition; + ret->ifTrue = (Expression*)ifTrue; + ret->ifFalse = (Expression*)ifFalse; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenLoop(BinaryenModuleRef module, const char* out, const char* in, BinaryenExpressionRef body) { + return Builder(*((Module*)module)).makeLoop(out ? Name(out) : Name(), in ? Name(in) : Name(), (Expression*)body); +} +BinaryenExpressionRef BinaryenBreak(BinaryenModuleRef module, const char* name, BinaryenExpressionRef value, BinaryenExpressionRef condition) { + return Builder(*((Module*)module)).makeBreak(name, (Expression*)value, (Expression*)condition); +} +BinaryenExpressionRef BinaryenSwitch(BinaryenModuleRef module, const char **names, BinaryenIndex numNames, const char* defaultName, BinaryenExpressionRef condition, BinaryenExpressionRef value) { + auto* ret = ((Module*)module)->allocator.alloc<Switch>(); + for (BinaryenIndex i = 0; i < numNames; i++) { + ret->targets.push_back(names[i]); + } + ret->default_ = defaultName; + ret->condition = (Expression*)condition; + ret->value = (Expression*)value; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenCall(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands) { + auto* ret = ((Module*)module)->allocator.alloc<Call>(); + ret->target = target; + for (BinaryenIndex i = 0; i < numOperands; i++) { + ret->operands.push_back((Expression*)operands[i]); + } + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenCallImport(BinaryenModuleRef module, const char *target, BinaryenExpressionRef* operands, BinaryenIndex numOperands) { + auto* ret = ((Module*)module)->allocator.alloc<CallImport>(); + ret->target = target; + for (BinaryenIndex i = 0; i < numOperands; i++) { + ret->operands.push_back((Expression*)operands[i]); + } + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenCallIndirect(BinaryenModuleRef module, BinaryenExpressionRef target, BinaryenExpressionRef* operands, BinaryenIndex numOperands, BinaryenFunctionTypeRef type) { + auto* ret = ((Module*)module)->allocator.alloc<CallIndirect>(); + ret->target = (Expression*)target; + for (BinaryenIndex i = 0; i < numOperands; i++) { + ret->operands.push_back((Expression*)operands[i]); + } + ret->fullType = (FunctionType*)type; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenGetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenType type) { + auto* ret = ((Module*)module)->allocator.alloc<GetLocal>(); + ret->index = index; + ret->type = WasmType(type); + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenSetLocal(BinaryenModuleRef module, BinaryenIndex index, BinaryenExpressionRef value) { + auto* ret = ((Module*)module)->allocator.alloc<SetLocal>(); + ret->index = index; + ret->value = (Expression*)value; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenLoad(BinaryenModuleRef module, uint32_t bytes, int8_t signed_, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr) { + auto* ret = ((Module*)module)->allocator.alloc<Load>(); + ret->bytes = bytes; + ret->signed_ = signed_; + ret->offset = offset; + ret->align = align; + ret->ptr = (Expression*)ptr; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenStore(BinaryenModuleRef module, uint32_t bytes, uint32_t offset, uint32_t align, BinaryenExpressionRef ptr, BinaryenExpressionRef value) { + auto* ret = ((Module*)module)->allocator.alloc<Store>(); + ret->bytes = bytes; + ret->offset = offset; + ret->align = align; + ret->ptr = (Expression*)ptr; + ret->value = (Expression*)value; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenConst(BinaryenModuleRef module, BinaryenLiteral value) { + return Builder(*((Module*)module)).makeConst(fromBinaryenLiteral(value)); +} +BinaryenExpressionRef BinaryenUnary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef value, BinaryenType type) { + return Builder(*((Module*)module)).makeUnary(UnaryOp(op), (Expression*)value, WasmType(type)); +} +BinaryenExpressionRef BinaryenBinary(BinaryenModuleRef module, BinaryenOp op, BinaryenExpressionRef left, BinaryenExpressionRef right) { + return Builder(*((Module*)module)).makeBinary(BinaryOp(op), (Expression*)left, (Expression*)right); +} +BinaryenExpressionRef BinaryenSelect(BinaryenModuleRef module, BinaryenExpressionRef condition, BinaryenExpressionRef ifTrue, BinaryenExpressionRef ifFalse) { + auto* ret = ((Module*)module)->allocator.alloc<Select>(); + ret->condition = (Expression*)condition; + ret->ifTrue = (Expression*)ifTrue; + ret->ifFalse = (Expression*)ifFalse; + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module, BinaryenExpressionRef value) { + return Builder(*((Module*)module)).makeReturn((Expression*)value); +} +BinaryenExpressionRef BinaryenHost(BinaryenModuleRef module, BinaryenOp op, const char* name, BinaryenExpressionRef* operands, BinaryenIndex numOperands) { + auto* ret = ((Module*)module)->allocator.alloc<Host>(); + ret->op = HostOp(op); + if (name) ret->nameOperand = name; + for (BinaryenIndex i = 0; i < numOperands; i++) { + ret->operands.push_back((Expression*)operands[i]); + } + ret->finalize(); + return ret; +} +BinaryenExpressionRef BinaryenNop(BinaryenModuleRef module) { + return ((Module*)module)->allocator.alloc<Nop>(); +} +BinaryenExpressionRef BinaryenUnreachable(BinaryenModuleRef module) { + return ((Module*)module)->allocator.alloc<Unreachable>(); +} + +// Functions + +BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module, const char* name, BinaryenFunctionTypeRef type, BinaryenType* localTypes, BinaryenIndex numLocalTypes, BinaryenExpressionRef body) { + auto* wasm = (Module*)module; + auto* ret = new Function; + ret->name = name; + ret->type = ((FunctionType*)type)->name; + auto* functionType = wasm->getFunctionType(ret->type); + ret->result = functionType->result; + ret->params = functionType->params; + for (BinaryenIndex i = 0; i < numLocalTypes; i++) { + ret->vars.push_back(WasmType(localTypes[i])); + } + ret->body = (Expression*)body; + wasm->addFunction(ret); + return ret; +} + +// Imports + +BinaryenImportRef BinaryenAddImport(BinaryenModuleRef module, const char* internalName, const char* externalModuleName, const char *externalBaseName, BinaryenFunctionTypeRef type) { + auto* wasm = (Module*)module; + auto* ret = new Import(); + ret->name = internalName; + ret->module = externalModuleName; + ret->base = externalBaseName; + ret->type = (FunctionType*)type; + wasm->addImport(ret); + return ret; +} + +// Exports + +BinaryenExportRef BinaryenAddExport(BinaryenModuleRef module, const char* internalName, const char* externalName) { + auto* wasm = (Module*)module; + auto* ret = new Export(); + ret->name = internalName; + ret->value = externalName; + wasm->addExport(ret); + return ret; +} + +// Function table. One per module + +void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenFunctionRef* functions, BinaryenIndex numFunctions) { + auto* wasm = (Module*)module; + for (BinaryenIndex i = 0; i < numFunctions; i++) { + wasm->table.names.push_back(((Function*)functions[i])->name); + } +} + +// Memory. One per module + +void BinaryenSetMemory(BinaryenModuleRef module, BinaryenIndex initial, BinaryenIndex maximum, const char* exportName, const char **segments, BinaryenIndex* segmentOffsets, BinaryenIndex* segmentSizes, BinaryenIndex numSegments) { + auto* wasm = (Module*)module; + wasm->memory.initial = initial; + wasm->memory.max = maximum; + wasm->memory.exportName = exportName; + for (BinaryenIndex i = 0; i < numSegments; i++) { + wasm->memory.segments.emplace_back(segmentOffsets[i], segments[i], segmentSizes[i]); + } +} + +// Start function. One per module + +void BinaryenSetStart(BinaryenModuleRef module, const char* name) { + auto* wasm = (Module*)module; + wasm->addStart(name); +} + +// +// ========== Module Operations ========== +// + +void BinaryenModulePrint(BinaryenModuleRef module) { + WasmPrinter::printModule((Module*)module); +} + +} // extern "C" |