5 #include "src/wasm/graph-builder-interface.h" 7 #include "src/compiler/wasm-compiler.h" 9 #include "src/handles.h" 10 #include "src/objects-inl.h" 11 #include "src/ostreams.h" 12 #include "src/wasm/decoder.h" 13 #include "src/wasm/function-body-decoder-impl.h" 14 #include "src/wasm/function-body-decoder.h" 15 #include "src/wasm/wasm-limits.h" 16 #include "src/wasm/wasm-linkage.h" 17 #include "src/wasm/wasm-module.h" 18 #include "src/wasm/wasm-opcodes.h" 31 enum State { kControlEnd, kUnreachable, kReached, kMerged };
36 compiler::WasmInstanceCacheNodes instance_cache;
39 bool reached()
const {
return state >= kReached; }
40 void Kill(State new_state = kControlEnd) {
48 if (state == kMerged) state = kReached;
52 #define BUILD(func, ...) \ 54 DCHECK(ssa_env_->reached()); \ 55 DCHECK(decoder->ok()); \ 56 return CheckForException(decoder, builder_->func(__VA_ARGS__)); \ 61 class WasmGraphBuildingInterface {
63 static constexpr Decoder::ValidateFlag validate = Decoder::kValidate;
64 using FullDecoder = WasmFullDecoder<validate, WasmGraphBuildingInterface>;
66 struct Value :
public ValueWithNamedConstructors<Value> {
70 struct TryInfo :
public ZoneObject {
72 TFNode* exception =
nullptr;
74 explicit TryInfo(SsaEnv* c) : catch_env(c) {}
77 struct Control :
public ControlWithNamedConstructors<Control, Value> {
81 int32_t previous_catch;
84 explicit WasmGraphBuildingInterface(compiler::WasmGraphBuilder* builder)
85 : builder_(builder) {}
87 void StartFunction(FullDecoder* decoder) {
89 reinterpret_cast<SsaEnv*
>(decoder->zone()->New(
sizeof(SsaEnv)));
90 uint32_t num_locals = decoder->NumLocals();
92 size_t size =
sizeof(TFNode*) * env_count;
93 ssa_env->state = SsaEnv::kReached;
95 size > 0 ?
reinterpret_cast<TFNode**
>(decoder->zone()->New(size))
100 TFNode* start = builder_->Start(
101 static_cast<int>(decoder->sig_->parameter_count() + 1 + 1));
102 ssa_env->effect = start;
103 ssa_env->control = start;
106 builder_->set_effect_ptr(&ssa_env->effect);
107 builder_->set_control_ptr(&ssa_env->control);
109 builder_->set_instance_node(builder_->Param(kWasmInstanceParameterIndex));
113 for (; index < decoder->sig_->parameter_count(); ++index) {
114 ssa_env->locals[index] = builder_->Param(index + 1);
116 while (index < num_locals) {
117 ValueType type = decoder->GetLocalType(index);
118 TFNode* node = DefaultValue(type);
119 while (index < num_locals && decoder->GetLocalType(index) == type) {
121 ssa_env->locals[index++] = node;
124 LoadContextIntoSsa(ssa_env);
129 void LoadContextIntoSsa(SsaEnv* ssa_env) {
130 if (!ssa_env || !ssa_env->reached())
return;
131 builder_->InitInstanceCache(&ssa_env->instance_cache);
134 void StartFunctionBody(FullDecoder* decoder, Control* block) {
135 SsaEnv* break_env = ssa_env_;
136 SetEnv(Steal(decoder->zone(), break_env));
137 block->end_env = break_env;
140 void FinishFunction(FullDecoder*) { builder_->PatchInStackCheckIfNeeded(); }
142 void OnFirstError(FullDecoder*) {}
144 void NextInstruction(FullDecoder*, WasmOpcode) {}
146 void Block(FullDecoder* decoder, Control* block) {
148 block->end_env = ssa_env_;
149 SetEnv(Steal(decoder->zone(), ssa_env_));
152 void Loop(FullDecoder* decoder, Control* block) {
153 SsaEnv* finish_try_env = Steal(decoder->zone(), ssa_env_);
154 block->end_env = finish_try_env;
156 SetEnv(PrepareForLoop(decoder, finish_try_env));
157 ssa_env_->SetNotMerged();
158 if (!decoder->ok())
return;
160 for (
uint32_t i = 0;
i < block->start_merge.arity; ++
i) {
161 Value& val = block->start_merge[
i];
162 val.node = builder_->Phi(val.type, 1, &val.node, block->end_env->control);
166 void Try(FullDecoder* decoder, Control* block) {
167 SsaEnv* outer_env = ssa_env_;
168 SsaEnv* catch_env = Split(decoder, outer_env);
171 catch_env->state = SsaEnv::kUnreachable;
172 SsaEnv* try_env = Steal(decoder->zone(), outer_env);
174 TryInfo* try_info =
new (decoder->zone()) TryInfo(catch_env);
175 block->end_env = outer_env;
176 block->try_info = try_info;
177 block->previous_catch = current_catch_;
178 current_catch_ =
static_cast<int32_t
>(decoder->control_depth() - 1);
181 void If(FullDecoder* decoder,
const Value& cond, Control* if_block) {
182 TFNode* if_true =
nullptr;
183 TFNode* if_false =
nullptr;
184 if (ssa_env_->reached()) {
185 BUILD(BranchNoHint, cond.node, &if_true, &if_false);
187 SsaEnv* end_env = ssa_env_;
188 SsaEnv* false_env = Split(decoder, ssa_env_);
189 false_env->control = if_false;
190 SsaEnv* true_env = Steal(decoder->zone(), ssa_env_);
191 true_env->control = if_true;
192 if_block->end_env = end_env;
193 if_block->false_env = false_env;
197 void FallThruTo(FullDecoder* decoder, Control* c) {
198 DCHECK(!c->is_loop());
199 MergeValuesInto(decoder, c, &c->end_merge);
202 void PopControl(FullDecoder* decoder, Control* block) {
203 if (!block->is_loop()) SetEnv(block->end_env);
206 void EndControl(FullDecoder* decoder, Control* block) { ssa_env_->Kill(); }
208 void UnOp(FullDecoder* decoder, WasmOpcode opcode, FunctionSig* sig,
210 result->node = BUILD(Unop, opcode, value.node, decoder->position());
213 void BinOp(FullDecoder* decoder, WasmOpcode opcode, FunctionSig* sig,
215 auto node = BUILD(Binop, opcode, lhs.node, rhs.node, decoder->position());
216 if (result) result->node = node;
219 void I32Const(FullDecoder* decoder,
Value* result, int32_t value) {
220 result->node = builder_->Int32Constant(value);
223 void I64Const(FullDecoder* decoder,
Value* result,
int64_t value) {
224 result->node = builder_->Int64Constant(value);
227 void F32Const(FullDecoder* decoder,
Value* result,
float value) {
228 result->node = builder_->Float32Constant(value);
231 void F64Const(FullDecoder* decoder,
Value* result,
double value) {
232 result->node = builder_->Float64Constant(value);
235 void RefNull(FullDecoder* decoder,
Value* result) {
236 result->node = builder_->RefNull();
239 void Drop(FullDecoder* decoder,
const Value& value) {}
241 void DoReturn(FullDecoder* decoder, Vector<Value> values,
bool implicit) {
243 DCHECK_EQ(1, decoder->control_depth());
244 SetEnv(decoder->control_at(0)->end_env);
246 size_t num_values = values.size();
247 TFNode** buffer = GetNodes(values);
248 for (
size_t i = 0;
i < num_values; ++
i) {
249 buffer[
i] = values[
i].node;
251 BUILD(Return, static_cast<uint32_t>(values.size()), buffer);
254 void GetLocal(FullDecoder* decoder,
Value* result,
255 const LocalIndexImmediate<validate>& imm) {
256 if (!ssa_env_->locals)
return;
257 result->node = ssa_env_->locals[imm.index];
260 void SetLocal(FullDecoder* decoder,
const Value& value,
261 const LocalIndexImmediate<validate>& imm) {
262 if (!ssa_env_->locals)
return;
263 ssa_env_->locals[imm.index] = value.node;
266 void TeeLocal(FullDecoder* decoder,
const Value& value,
Value* result,
267 const LocalIndexImmediate<validate>& imm) {
268 result->node = value.node;
269 if (!ssa_env_->locals)
return;
270 ssa_env_->locals[imm.index] = value.node;
273 void GetGlobal(FullDecoder* decoder,
Value* result,
274 const GlobalIndexImmediate<validate>& imm) {
275 result->node = BUILD(GetGlobal, imm.index);
278 void SetGlobal(FullDecoder* decoder,
const Value& value,
279 const GlobalIndexImmediate<validate>& imm) {
280 BUILD(SetGlobal, imm.index, value.node);
283 void Unreachable(FullDecoder* decoder) {
284 BUILD(Unreachable, decoder->position());
287 void Select(FullDecoder* decoder,
const Value& cond,
const Value& fval,
290 BUILD(BranchNoHint, cond.node, &controls[0], &controls[1]);
291 TFNode* merge = BUILD(Merge, 2, controls);
292 TFNode* vals[2] = {tval.node, fval.node};
293 TFNode* phi = BUILD(Phi, tval.type, 2, vals, merge);
295 ssa_env_->control = merge;
298 void Br(FullDecoder* decoder, Control* target) {
299 MergeValuesInto(decoder, target, target->br_merge());
302 void BrIf(FullDecoder* decoder,
const Value& cond, Control* target) {
303 SsaEnv* fenv = ssa_env_;
304 SsaEnv* tenv = Split(decoder, fenv);
305 fenv->SetNotMerged();
306 BUILD(BranchNoHint, cond.node, &tenv->control, &fenv->control);
312 void BrTable(FullDecoder* decoder,
const BranchTableImmediate<validate>& imm,
314 if (imm.table_count == 0) {
316 uint32_t target = BranchTableIterator<validate>(decoder, imm).next();
317 Br(decoder, decoder->control_at(target));
321 SsaEnv* break_env = ssa_env_;
323 TFNode* sw = BUILD(Switch, imm.table_count + 1, key.node);
325 SsaEnv* copy = Steal(decoder->zone(), break_env);
327 BranchTableIterator<validate> iterator(decoder, imm);
328 while (iterator.has_next()) {
331 ssa_env_ = Split(decoder, copy);
333 (
i == imm.table_count) ? BUILD(IfDefault, sw) : BUILD(IfValue,
i, sw);
334 Br(decoder, decoder->control_at(target));
336 DCHECK(decoder->ok());
337 ssa_env_ = break_env;
340 void Else(FullDecoder* decoder, Control* if_block) {
341 SetEnv(if_block->false_env);
344 void LoadMem(FullDecoder* decoder, LoadType type,
345 const MemoryAccessImmediate<validate>& imm,
const Value& index,
348 BUILD(LoadMem, type.value_type(), type.mem_type(), index.node,
349 imm.offset, imm.alignment, decoder->position());
352 void StoreMem(FullDecoder* decoder, StoreType type,
353 const MemoryAccessImmediate<validate>& imm,
const Value& index,
354 const Value& value) {
355 BUILD(StoreMem, type.mem_rep(), index.node, imm.offset, imm.alignment,
356 value.node, decoder->position(), type.value_type());
359 void CurrentMemoryPages(FullDecoder* decoder,
Value* result) {
360 result->node = BUILD(CurrentMemoryPages);
363 void MemoryGrow(FullDecoder* decoder,
const Value& value,
Value* result) {
364 result->node = BUILD(MemoryGrow, value.node);
366 LoadContextIntoSsa(ssa_env_);
369 void CallDirect(FullDecoder* decoder,
370 const CallFunctionImmediate<validate>& imm,
372 DoCall(decoder,
nullptr, imm.sig, imm.index, args, returns);
375 void CallIndirect(FullDecoder* decoder,
const Value& index,
376 const CallIndirectImmediate<validate>& imm,
378 DoCall(decoder, index.node, imm.sig, imm.sig_index, args, returns);
381 void SimdOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
383 TFNode** inputs = GetNodes(args);
384 TFNode* node = BUILD(SimdOp, opcode, inputs);
385 if (result) result->node = node;
388 void SimdLaneOp(FullDecoder* decoder, WasmOpcode opcode,
389 const SimdLaneImmediate<validate> imm, Vector<Value> inputs,
391 TFNode** nodes = GetNodes(inputs);
392 result->node = BUILD(SimdLaneOp, opcode, imm.lane, nodes);
395 void SimdShiftOp(FullDecoder* decoder, WasmOpcode opcode,
396 const SimdShiftImmediate<validate> imm,
const Value& input,
398 TFNode* inputs[] = {input.node};
399 result->node = BUILD(SimdShiftOp, opcode, imm.shift, inputs);
402 void Simd8x16ShuffleOp(FullDecoder* decoder,
403 const Simd8x16ShuffleImmediate<validate>& imm,
406 TFNode* input_nodes[] = {input0.node, input1.node};
407 result->node = BUILD(Simd8x16ShuffleOp, imm.shuffle, input_nodes);
410 void Throw(FullDecoder* decoder,
const ExceptionIndexImmediate<validate>& imm,
411 const Vector<Value>& value_args) {
412 int count = value_args.length();
413 ZoneVector<TFNode*> args(count, decoder->zone());
414 for (
int i = 0;
i < count; ++
i) {
415 args[
i] = value_args[
i].node;
417 BUILD(Throw, imm.index, imm.exception, VectorOf(args));
418 builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
421 void Rethrow(FullDecoder* decoder, Control* block) {
422 DCHECK(block->is_try_catchall() || block->is_try_catch());
423 TFNode* exception = block->try_info->exception;
424 BUILD(Rethrow, exception);
425 builder_->TerminateThrow(ssa_env_->effect, ssa_env_->control);
428 void CatchException(FullDecoder* decoder,
429 const ExceptionIndexImmediate<validate>& imm,
430 Control* block, Vector<Value> values) {
431 DCHECK(block->is_try_catch());
432 TFNode* exception = block->try_info->exception;
433 current_catch_ = block->previous_catch;
434 SsaEnv* catch_env = block->try_info->catch_env;
440 DCHECK_EQ(exception !=
nullptr, ssa_env_->reached());
441 if (exception ==
nullptr) {
442 block->reachability = kSpecOnlyReachable;
446 TFNode* if_catch =
nullptr;
447 TFNode* if_no_catch =
nullptr;
450 TFNode* caught_tag = BUILD(GetExceptionTag, exception);
451 TFNode* exception_tag = BUILD(LoadExceptionTagFromTable, imm.index);
452 TFNode* compare = BUILD(ExceptionTagEqual, caught_tag, exception_tag);
453 BUILD(BranchNoHint, compare, &if_catch, &if_no_catch);
457 SsaEnv* if_no_catch_env = Split(decoder, ssa_env_);
458 if_no_catch_env->control = if_no_catch;
459 SsaEnv* if_catch_env = Steal(decoder->zone(), ssa_env_);
460 if_catch_env->control = if_catch;
461 block->try_info->catch_env = if_no_catch_env;
465 SetEnv(if_catch_env);
468 TFNode** caught_values =
469 builder_->GetExceptionValues(exception, imm.exception);
470 for (
size_t i = 0, e = values.size();
i < e; ++
i) {
471 values[
i].node = caught_values[
i];
475 void CatchAll(FullDecoder* decoder, Control* block) {
476 DCHECK(block->is_try_catchall() || block->is_try_catch());
477 TFNode* exception = block->try_info->exception;
478 current_catch_ = block->previous_catch;
479 SsaEnv* catch_env = block->try_info->catch_env;
485 DCHECK_EQ(exception !=
nullptr, ssa_env_->reached());
486 if (exception ==
nullptr) {
487 block->reachability = kSpecOnlyReachable;
492 void AtomicOp(FullDecoder* decoder, WasmOpcode opcode, Vector<Value> args,
493 const MemoryAccessImmediate<validate>& imm,
Value* result) {
494 TFNode** inputs = GetNodes(args);
495 TFNode* node = BUILD(AtomicOp, opcode, inputs, imm.alignment, imm.offset,
496 decoder->position());
497 if (result) result->node = node;
500 void MemoryInit(FullDecoder* decoder,
501 const MemoryInitImmediate<validate>& imm,
502 Vector<Value> args) {
503 BUILD(Unreachable, decoder->position());
505 void MemoryDrop(FullDecoder* decoder,
506 const MemoryDropImmediate<validate>& imm) {
507 BUILD(Unreachable, decoder->position());
509 void MemoryCopy(FullDecoder* decoder,
510 const MemoryIndexImmediate<validate>& imm,
511 Vector<Value> args) {
512 BUILD(Unreachable, decoder->position());
514 void MemoryFill(FullDecoder* decoder,
515 const MemoryIndexImmediate<validate>& imm,
516 Vector<Value> args) {
517 BUILD(Unreachable, decoder->position());
519 void TableInit(FullDecoder* decoder,
const TableInitImmediate<validate>& imm,
520 Vector<Value> args) {
521 BUILD(Unreachable, decoder->position());
523 void TableDrop(FullDecoder* decoder,
524 const TableDropImmediate<validate>& imm) {
525 BUILD(Unreachable, decoder->position());
527 void TableCopy(FullDecoder* decoder,
const TableIndexImmediate<validate>& imm,
528 Vector<Value> args) {
529 BUILD(Unreachable, decoder->position());
534 compiler::WasmGraphBuilder* builder_;
535 uint32_t current_catch_ = kNullCatch;
537 TryInfo* current_try_info(FullDecoder* decoder) {
538 return decoder->control_at(decoder->control_depth() - 1 - current_catch_)
542 TFNode** GetNodes(
Value* values,
size_t count) {
543 TFNode** nodes = builder_->Buffer(count);
544 for (
size_t i = 0;
i < count; ++
i) {
545 nodes[
i] = values[
i].node;
550 TFNode** GetNodes(Vector<Value> values) {
551 return GetNodes(values.start(), values.size());
554 void SetEnv(SsaEnv* env) {
556 if (FLAG_trace_wasm_decoder) {
559 switch (env->state) {
560 case SsaEnv::kReached:
563 case SsaEnv::kUnreachable:
566 case SsaEnv::kMerged:
569 case SsaEnv::kControlEnd:
574 PrintF(
"{set_env = %p, state = %c", static_cast<void*>(env), state);
575 if (env && env->control) {
576 PrintF(
", control = ");
577 compiler::WasmGraphBuilder::PrintDebugName(env->control);
584 builder_->set_control_ptr(&env->control);
585 builder_->set_effect_ptr(&env->effect);
586 builder_->set_instance_cache(&env->instance_cache);
589 TFNode* CheckForException(FullDecoder* decoder, TFNode* node) {
590 if (node ==
nullptr)
return nullptr;
592 const bool inside_try_scope = current_catch_ != kNullCatch;
594 if (!inside_try_scope)
return node;
596 TFNode* if_success =
nullptr;
597 TFNode* if_exception =
nullptr;
598 if (!builder_->ThrowsException(node, &if_success, &if_exception)) {
602 SsaEnv* success_env = Steal(decoder->zone(), ssa_env_);
603 success_env->control = if_success;
605 SsaEnv* exception_env = Split(decoder, success_env);
606 exception_env->control = if_exception;
607 TryInfo* try_info = current_try_info(decoder);
608 Goto(decoder, exception_env, try_info->catch_env);
609 TFNode* exception = try_info->exception;
610 if (exception ==
nullptr) {
611 DCHECK_EQ(SsaEnv::kReached, try_info->catch_env->state);
612 try_info->exception = if_exception;
614 DCHECK_EQ(SsaEnv::kMerged, try_info->catch_env->state);
615 try_info->exception = builder_->CreateOrMergeIntoPhi(
616 MachineRepresentation::kWord32, try_info->catch_env->control,
617 try_info->exception, if_exception);
624 TFNode* DefaultValue(ValueType type) {
627 return builder_->Int32Constant(0);
629 return builder_->Int64Constant(0);
631 return builder_->Float32Constant(0);
633 return builder_->Float64Constant(0);
635 return builder_->S128Zero();
638 return builder_->RefNull();
644 void MergeValuesInto(FullDecoder* decoder, Control* c, Merge<Value>* merge) {
645 DCHECK(merge == &c->start_merge || merge == &c->end_merge);
646 if (!ssa_env_->reached())
return;
648 SsaEnv* target = c->end_env;
649 const bool first = target->state == SsaEnv::kUnreachable;
650 Goto(decoder, ssa_env_, target);
653 decoder->stack_size() - decoder->control_at(0)->stack_depth;
654 uint32_t start = avail >= merge->arity ? 0 : merge->arity - avail;
656 auto& val = decoder->GetMergeValueFromStack(c, merge,
i);
657 auto& old = (*merge)[
i];
658 DCHECK_NOT_NULL(val.node);
659 DCHECK(val.type == old.type || val.type == kWasmVar);
660 old.node = first ? val.node
661 : builder_->CreateOrMergeIntoPhi(
662 ValueTypes::MachineRepresentationFor(old.type),
663 target->control, old.node, val.node);
667 void Goto(FullDecoder* decoder, SsaEnv* from, SsaEnv* to) {
669 if (!from->reached())
return;
671 case SsaEnv::kUnreachable: {
672 to->state = SsaEnv::kReached;
673 to->locals = from->locals;
674 to->control = from->control;
675 to->effect = from->effect;
676 to->instance_cache = from->instance_cache;
679 case SsaEnv::kReached: {
680 to->state = SsaEnv::kMerged;
682 TFNode* controls[] = {to->control, from->control};
683 TFNode* merge = builder_->Merge(2, controls);
686 if (from->effect != to->effect) {
687 TFNode* effects[] = {to->effect, from->effect, merge};
688 to->effect = builder_->EffectPhi(2, effects, merge);
691 for (
int i = decoder->NumLocals() - 1;
i >= 0;
i--) {
692 TFNode* a = to->locals[
i];
693 TFNode* b = from->locals[
i];
695 TFNode* vals[] = {a, b};
697 builder_->Phi(decoder->GetLocalType(
i), 2, vals, merge);
701 builder_->NewInstanceCacheMerge(&to->instance_cache,
702 &from->instance_cache, merge);
705 case SsaEnv::kMerged: {
706 TFNode* merge = to->control;
708 builder_->AppendToMerge(merge, from->control);
710 to->effect = builder_->CreateOrMergeIntoEffectPhi(merge, to->effect,
713 for (
int i = decoder->NumLocals() - 1;
i >= 0;
i--) {
714 to->locals[
i] = builder_->CreateOrMergeIntoPhi(
715 ValueTypes::MachineRepresentationFor(decoder->GetLocalType(
i)),
716 merge, to->locals[
i], from->locals[
i]);
719 builder_->MergeInstanceCacheInto(&to->instance_cache,
720 &from->instance_cache, merge);
729 SsaEnv* PrepareForLoop(FullDecoder* decoder, SsaEnv* env) {
730 if (!env->reached())
return Split(decoder, env);
731 env->state = SsaEnv::kMerged;
733 env->control = builder_->Loop(env->control);
734 env->effect = builder_->EffectPhi(1, &env->effect, env->control);
735 builder_->TerminateLoop(env->effect, env->control);
737 BitVector* assigned = WasmDecoder<validate>::AnalyzeLoopAssignment(
738 decoder, decoder->pc(), decoder->total_locals() + 1, decoder->zone());
739 if (decoder->failed())
return env;
740 if (assigned !=
nullptr) {
742 int instance_cache_index = decoder->total_locals();
743 for (
int i = decoder->NumLocals() - 1;
i >= 0;
i--) {
744 if (!assigned->Contains(
i))
continue;
745 env->locals[
i] = builder_->Phi(decoder->GetLocalType(
i), 1,
746 &env->locals[
i], env->control);
749 if (assigned->Contains(instance_cache_index)) {
750 builder_->PrepareInstanceCacheForLoop(&env->instance_cache,
754 SsaEnv* loop_body_env = Split(decoder, env);
755 builder_->StackCheck(decoder->position(), &(loop_body_env->effect),
756 &(loop_body_env->control));
757 return loop_body_env;
761 for (
int i = decoder->NumLocals() - 1;
i >= 0;
i--) {
762 env->locals[
i] = builder_->Phi(decoder->GetLocalType(
i), 1,
763 &env->locals[
i], env->control);
767 builder_->PrepareInstanceCacheForLoop(&env->instance_cache, env->control);
769 SsaEnv* loop_body_env = Split(decoder, env);
770 builder_->StackCheck(decoder->position(), &loop_body_env->effect,
771 &loop_body_env->control);
772 return loop_body_env;
776 SsaEnv* Split(FullDecoder* decoder, SsaEnv* from) {
777 DCHECK_NOT_NULL(from);
779 reinterpret_cast<SsaEnv*
>(decoder->zone()->New(
sizeof(SsaEnv)));
780 size_t size =
sizeof(TFNode*) * decoder->NumLocals();
781 result->control = from->control;
782 result->effect = from->effect;
784 if (from->reached()) {
785 result->state = SsaEnv::kReached;
787 size > 0 ?
reinterpret_cast<TFNode**
>(decoder->zone()->New(size))
789 memcpy(result->locals, from->locals, size);
790 result->instance_cache = from->instance_cache;
792 result->state = SsaEnv::kUnreachable;
793 result->locals =
nullptr;
794 result->instance_cache = {};
802 SsaEnv* Steal(Zone* zone, SsaEnv* from) {
803 DCHECK_NOT_NULL(from);
804 if (!from->reached())
return UnreachableEnv(zone);
805 SsaEnv* result =
reinterpret_cast<SsaEnv*
>(zone->New(
sizeof(SsaEnv)));
806 result->state = SsaEnv::kReached;
807 result->locals = from->locals;
808 result->control = from->control;
809 result->effect = from->effect;
810 result->instance_cache = from->instance_cache;
811 from->Kill(SsaEnv::kUnreachable);
816 SsaEnv* UnreachableEnv(Zone* zone) {
817 SsaEnv* result =
reinterpret_cast<SsaEnv*
>(zone->New(
sizeof(SsaEnv)));
818 result->state = SsaEnv::kUnreachable;
819 result->control =
nullptr;
820 result->effect =
nullptr;
821 result->locals =
nullptr;
822 result->instance_cache = {};
826 void DoCall(FullDecoder* decoder, TFNode* index_node, FunctionSig* sig,
828 int param_count =
static_cast<int>(sig->parameter_count());
829 TFNode** arg_nodes = builder_->Buffer(param_count + 1);
830 TFNode** return_nodes =
nullptr;
831 arg_nodes[0] = index_node;
832 for (
int i = 0;
i < param_count; ++
i) {
833 arg_nodes[
i + 1] = args[
i].node;
836 BUILD(CallIndirect, index, arg_nodes, &return_nodes, decoder->position());
838 BUILD(CallDirect, index, arg_nodes, &return_nodes, decoder->position());
840 int return_count =
static_cast<int>(sig->return_count());
841 for (
int i = 0;
i < return_count; ++
i) {
842 returns[
i].node = return_nodes[
i];
846 LoadContextIntoSsa(ssa_env_);
852 DecodeResult BuildTFGraph(AccountingAllocator* allocator,
853 const WasmFeatures& enabled,
854 const wasm::WasmModule* module,
855 compiler::WasmGraphBuilder* builder,
856 WasmFeatures* detected,
const FunctionBody& body,
857 compiler::NodeOriginTable* node_origins) {
858 Zone zone(allocator, ZONE_NAME);
859 WasmFullDecoder<Decoder::kValidate, WasmGraphBuildingInterface> decoder(
860 &zone, module, enabled, detected, body, builder);
862 builder->AddBytecodePositionDecorator(node_origins, &decoder);
866 builder->RemoveBytecodePositionDecorator();
868 return decoder.toResult(
nullptr);