1// Copyright 2015 the V8 project authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <stdlib.h> 6#include <string.h> 7 8#include "src/wasm/encoder.h" 9#include "src/wasm/wasm-macro-gen.h" 10#include "src/wasm/wasm-module.h" 11#include "src/wasm/wasm-opcodes.h" 12 13#include "test/cctest/cctest.h" 14 15using namespace v8::base; 16using namespace v8::internal; 17using namespace v8::internal::compiler; 18using namespace v8::internal::wasm; 19 20 21namespace { 22void TestModule(WasmModuleIndex* module, int32_t expected_result) { 23 Isolate* isolate = CcTest::InitIsolateOnce(); 24 int32_t result = 25 CompileAndRunWasmModule(isolate, module->Begin(), module->End()); 26 CHECK_EQ(expected_result, result); 27} 28} // namespace 29 30 31// A raw test that skips the WasmModuleBuilder. 32TEST(Run_WasmModule_CallAdd_rev) { 33 static const byte data[] = { 34 // sig#0 ------------------------------------------ 35 kDeclSignatures, 2, 0, kLocalI32, // void -> int 36 2, kLocalI32, kLocalI32, kLocalI32, // int,int -> int 37 // func#0 (main) ---------------------------------- 38 kDeclFunctions, 2, kDeclFunctionExport, 0, 0, // sig index 39 6, 0, // body size 40 kExprCallFunction, 1, // -- 41 kExprI8Const, 77, // -- 42 kExprI8Const, 22, // -- 43 // func#1 ----------------------------------------- 44 0, // no name, not exported 45 1, 0, // sig index 46 5, 0, // body size 47 kExprI32Add, // -- 48 kExprGetLocal, 0, // -- 49 kExprGetLocal, 1, // -- 50 }; 51 52 Isolate* isolate = CcTest::InitIsolateOnce(); 53 int32_t result = 54 CompileAndRunWasmModule(isolate, data, data + arraysize(data)); 55 CHECK_EQ(99, result); 56} 57 58 59TEST(Run_WasmModule_Return114) { 60 static const int32_t kReturnValue = 114; 61 Zone zone; 62 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 63 uint16_t f_index = builder->AddFunction(); 64 WasmFunctionBuilder* f = builder->FunctionAt(f_index); 65 f->ReturnType(kAstI32); 66 f->Exported(1); 67 byte code[] = {WASM_I8(kReturnValue)}; 68 f->EmitCode(code, sizeof(code)); 69 WasmModuleWriter* writer = builder->Build(&zone); 70 TestModule(writer->WriteTo(&zone), kReturnValue); 71} 72 73 74TEST(Run_WasmModule_CallAdd) { 75 Zone zone; 76 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 77 uint16_t f1_index = builder->AddFunction(); 78 WasmFunctionBuilder* f = builder->FunctionAt(f1_index); 79 f->ReturnType(kAstI32); 80 uint16_t param1 = f->AddParam(kAstI32); 81 uint16_t param2 = f->AddParam(kAstI32); 82 byte code1[] = {WASM_I32_ADD(WASM_GET_LOCAL(param1), WASM_GET_LOCAL(param2))}; 83 uint32_t local_indices1[] = {2, 4}; 84 f->EmitCode(code1, sizeof(code1), local_indices1, sizeof(local_indices1) / 4); 85 uint16_t f2_index = builder->AddFunction(); 86 f = builder->FunctionAt(f2_index); 87 f->ReturnType(kAstI32); 88 f->Exported(1); 89 byte code2[] = {WASM_CALL_FUNCTION(f1_index, WASM_I8(77), WASM_I8(22))}; 90 f->EmitCode(code2, sizeof(code2)); 91 WasmModuleWriter* writer = builder->Build(&zone); 92 TestModule(writer->WriteTo(&zone), 99); 93} 94 95 96TEST(Run_WasmModule_ReadLoadedDataSegment) { 97 static const byte kDataSegmentDest0 = 12; 98 Zone zone; 99 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 100 uint16_t f_index = builder->AddFunction(); 101 WasmFunctionBuilder* f = builder->FunctionAt(f_index); 102 f->ReturnType(kAstI32); 103 f->Exported(1); 104 byte code[] = { 105 WASM_LOAD_MEM(MachineType::Int32(), WASM_I8(kDataSegmentDest0))}; 106 f->EmitCode(code, sizeof(code)); 107 byte data[] = {0xaa, 0xbb, 0xcc, 0xdd}; 108 builder->AddDataSegment(new (&zone) WasmDataSegmentEncoder( 109 &zone, data, sizeof(data), kDataSegmentDest0)); 110 WasmModuleWriter* writer = builder->Build(&zone); 111 TestModule(writer->WriteTo(&zone), 0xddccbbaa); 112} 113 114 115#if defined(__has_feature) 116#if __has_feature(address_sanitizer) 117#define V8_WITH_ASAN 1 118#endif 119#endif 120 121 122#if !defined(V8_WITH_ASAN) 123// TODO(bradnelson): Figure out why this crashes under asan. 124TEST(Run_WasmModule_CheckMemoryIsZero) { 125 static const int kCheckSize = 16 * 1024; 126 Zone zone; 127 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 128 uint16_t f_index = builder->AddFunction(); 129 WasmFunctionBuilder* f = builder->FunctionAt(f_index); 130 f->ReturnType(kAstI32); 131 uint16_t localIndex = f->AddLocal(kAstI32); 132 f->Exported(1); 133 byte code[] = {WASM_BLOCK( 134 2, 135 WASM_WHILE( 136 WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I32(kCheckSize)), 137 WASM_IF_ELSE( 138 WASM_LOAD_MEM(MachineType::Int32(), WASM_GET_LOCAL(localIndex)), 139 WASM_BRV(2, WASM_I8(-1)), WASM_INC_LOCAL_BY(localIndex, 4))), 140 WASM_I8(11))}; 141 uint32_t local_indices[] = {7, 19, 25, 28}; 142 f->EmitCode(code, sizeof(code), local_indices, sizeof(local_indices) / 4); 143 WasmModuleWriter* writer = builder->Build(&zone); 144 TestModule(writer->WriteTo(&zone), 11); 145} 146#endif 147 148 149#if !defined(V8_WITH_ASAN) 150// TODO(bradnelson): Figure out why this crashes under asan. 151TEST(Run_WasmModule_CallMain_recursive) { 152 Zone zone; 153 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 154 uint16_t f_index = builder->AddFunction(); 155 WasmFunctionBuilder* f = builder->FunctionAt(f_index); 156 f->ReturnType(kAstI32); 157 uint16_t localIndex = f->AddLocal(kAstI32); 158 f->Exported(1); 159 byte code[] = {WASM_BLOCK( 160 2, WASM_SET_LOCAL(localIndex, 161 WASM_LOAD_MEM(MachineType::Int32(), WASM_ZERO)), 162 WASM_IF_ELSE(WASM_I32_LTS(WASM_GET_LOCAL(localIndex), WASM_I8(5)), 163 WASM_BLOCK(2, WASM_STORE_MEM(MachineType::Int32(), WASM_ZERO, 164 WASM_INC_LOCAL(localIndex)), 165 WASM_BRV(1, WASM_CALL_FUNCTION0(0))), 166 WASM_BRV(0, WASM_I8(55))))}; 167 uint32_t local_indices[] = {3, 11, 21, 24}; 168 f->EmitCode(code, sizeof(code), local_indices, sizeof(local_indices) / 4); 169 WasmModuleWriter* writer = builder->Build(&zone); 170 TestModule(writer->WriteTo(&zone), 55); 171} 172#endif 173 174 175#if !defined(V8_WITH_ASAN) 176// TODO(bradnelson): Figure out why this crashes under asan. 177TEST(Run_WasmModule_Global) { 178 Zone zone; 179 WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone); 180 uint32_t global1 = builder->AddGlobal(MachineType::Int32(), 0); 181 uint32_t global2 = builder->AddGlobal(MachineType::Int32(), 0); 182 uint16_t f1_index = builder->AddFunction(); 183 WasmFunctionBuilder* f = builder->FunctionAt(f1_index); 184 f->ReturnType(kAstI32); 185 byte code1[] = { 186 WASM_I32_ADD(WASM_LOAD_GLOBAL(global1), WASM_LOAD_GLOBAL(global2))}; 187 f->EmitCode(code1, sizeof(code1)); 188 uint16_t f2_index = builder->AddFunction(); 189 f = builder->FunctionAt(f2_index); 190 f->ReturnType(kAstI32); 191 f->Exported(1); 192 byte code2[] = {WASM_STORE_GLOBAL(global1, WASM_I32(56)), 193 WASM_STORE_GLOBAL(global2, WASM_I32(41)), 194 WASM_RETURN(WASM_CALL_FUNCTION0(f1_index))}; 195 f->EmitCode(code2, sizeof(code2)); 196 WasmModuleWriter* writer = builder->Build(&zone); 197 TestModule(writer->WriteTo(&zone), 97); 198} 199#endif 200