Skip to content

Commit a2b8ad7

Browse files
committed
wasm2c: Fix handling of locals in setjmp targets
1 parent 196ea1d commit a2b8ad7

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

src/c-writer.cc

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,11 @@ class CWriter {
426426
void WriteImportProperties(CWriterPhase);
427427
void WriteFuncs();
428428
void BeginFunction(const Func&);
429-
void FinishFunction();
429+
void FinishFunction(size_t);
430430
void Write(const Func&);
431431
void WriteTailCallee(const Func&);
432432
void WriteParamsAndLocals();
433-
void WriteParams(const std::vector<std::string>& index_to_name);
433+
void WriteParams(const std::vector<std::string>& index_to_name, bool setjmp_safe = false);
434434
void WriteParamSymbols(const std::vector<std::string>& index_to_name);
435435
void WriteParamTypes(const FuncDeclaration& decl);
436436
void WriteLocals(const std::vector<std::string>& index_to_name);
@@ -444,7 +444,7 @@ class CWriter {
444444
void Unspill(const TypeVector&);
445445

446446
template <typename Vars, typename TypeOf, typename ToDo>
447-
void WriteVarsByType(const Vars&, const TypeOf&, const ToDo&);
447+
void WriteVarsByType(const Vars&, const TypeOf&, const ToDo&, bool);
448448

449449
template <typename sources>
450450
void Spill(const TypeVector&, const sources& src);
@@ -3044,15 +3044,15 @@ void CWriter::BeginFunction(const Func& func) {
30443044
Write(Newline());
30453045
}
30463046

3047-
void CWriter::FinishFunction() {
3047+
void CWriter::FinishFunction(size_t stack_var_section) {
30483048
for (size_t i = 0; i < func_sections_.size(); ++i) {
30493049
auto& [condition, stream] = func_sections_.at(i);
30503050
std::unique_ptr<OutputBuffer> buf = stream.ReleaseOutputBuffer();
30513051
if (condition.empty() || func_includes_.count(condition)) {
30523052
stream_->WriteData(buf->data.data(), buf->data.size());
30533053
}
30543054

3055-
if (i == 0) {
3055+
if (i == stack_var_section) {
30563056
WriteStackVarDeclarations(); // these come immediately after section #0
30573057
// (return type/name/params/locals)
30583058
}
@@ -3072,6 +3072,7 @@ void CWriter::Write(const Func& func) {
30723072
WriteParamsAndLocals();
30733073
Write("FUNC_PROLOGUE;", Newline());
30743074

3075+
size_t stack_vars_section = func_sections_.size() - 1;
30753076
PushFuncSection();
30763077

30773078
std::string label = DefineLabelName(kImplicitFuncLabel);
@@ -3095,13 +3096,14 @@ void CWriter::Write(const Func& func) {
30953096
}
30963097

30973098
stream_ = prev_stream;
3098-
FinishFunction();
3099+
FinishFunction(stack_vars_section);
30993100
}
31003101

31013102
template <typename Vars, typename TypeOf, typename ToDo>
31023103
void CWriter::WriteVarsByType(const Vars& vars,
31033104
const TypeOf& typeoffunc,
3104-
const ToDo& todo) {
3105+
const ToDo& todo,
3106+
bool setjmp_safe) {
31053107
for (Type type : {Type::I32, Type::I64, Type::F32, Type::F64, Type::V128,
31063108
Type::FuncRef, Type::ExternRef}) {
31073109
Index var_index = 0;
@@ -3110,6 +3112,11 @@ void CWriter::WriteVarsByType(const Vars& vars,
31103112
if (typeoffunc(var) == type) {
31113113
if (count == 0) {
31123114
Write(type, " ");
3115+
if (setjmp_safe) {
3116+
PushFuncSection("exceptions");
3117+
Write("volatile ");
3118+
PushFuncSection();
3119+
}
31133120
Indent(4);
31143121
} else {
31153122
Write(", ");
@@ -3145,14 +3152,15 @@ void CWriter::WriteTailCallee(const Func& func) {
31453152
if (func.GetNumParams()) {
31463153
WriteVarsByType(
31473154
func.decl.sig.param_types, [](auto x) { return x; },
3148-
[&](Index i, Type) { Write(DefineParamName(index_to_name[i])); });
3155+
[&](Index i, Type) { Write(DefineParamName(index_to_name[i])); }, true);
31493156
Write(OpenBrace(), func.decl.sig.param_types, " tmp;", Newline(),
31503157
"wasm_rt_memcpy(&tmp, tail_call_stack, sizeof(tmp));", Newline());
31513158
Unspill(func.decl.sig.param_types,
31523159
[&](auto i) { return ParamName(index_to_name[i]); });
31533160
Write(CloseBrace(), Newline());
31543161
}
31553162

3163+
size_t stack_vars_section = func_sections_.size() - 1;
31563164
WriteLocals(index_to_name);
31573165

31583166
PushFuncSection();
@@ -3176,19 +3184,19 @@ void CWriter::WriteTailCallee(const Func& func) {
31763184
Write("next->fn = NULL;", Newline());
31773185

31783186
stream_ = prev_stream;
3179-
FinishFunction();
3187+
FinishFunction(stack_vars_section);
31803188
}
31813189

31823190
void CWriter::WriteParamsAndLocals() {
31833191
std::vector<std::string> index_to_name;
31843192
MakeTypeBindingReverseMapping(func_->GetNumParamsAndLocals(), func_->bindings,
31853193
&index_to_name);
3186-
WriteParams(index_to_name);
3194+
WriteParams(index_to_name, true);
31873195
Write(" ", OpenBrace());
31883196
WriteLocals(index_to_name);
31893197
}
31903198

3191-
void CWriter::WriteParams(const std::vector<std::string>& index_to_name) {
3199+
void CWriter::WriteParams(const std::vector<std::string>& index_to_name, bool setjmp_safe) {
31923200
Write(ModuleInstanceTypeName(), "* instance");
31933201
if (func_->GetNumParams() != 0) {
31943202
Indent(4);
@@ -3197,7 +3205,13 @@ void CWriter::WriteParams(const std::vector<std::string>& index_to_name) {
31973205
if (i != 0 && (i % 8) == 0) {
31983206
Write(Newline());
31993207
}
3200-
Write(func_->GetParamType(i), " ", DefineParamName(index_to_name[i]));
3208+
Write(func_->GetParamType(i), " ");
3209+
if (setjmp_safe) {
3210+
PushFuncSection("exceptions");
3211+
Write("volatile ");
3212+
PushFuncSection();
3213+
}
3214+
Write(DefineParamName(index_to_name[i]));
32013215
}
32023216
Dedent(4);
32033217
}
@@ -3241,13 +3255,16 @@ void CWriter::WriteLocals(const std::vector<std::string>& index_to_name) {
32413255
} else {
32423256
Write("0");
32433257
}
3244-
});
3258+
}, true);
32453259
}
32463260

32473261
void CWriter::WriteStackVarDeclarations() {
3262+
// NOTE: setjmp_safe must be false, can't push func sections in here because
3263+
// this is called from FinishFunction.
3264+
// (luckily, we don't need setjmp_safe for these.)
32483265
WriteVarsByType(
32493266
stack_var_sym_map_, [](auto stp_name) { return stp_name.first.second; },
3250-
[&](Index, auto& stp_name) { Write(stp_name.second); });
3267+
[&](Index, auto& stp_name) { Write(stp_name.second); }, false);
32513268
}
32523269

32533270
void CWriter::Write(const Block& block) {
@@ -3263,6 +3280,7 @@ void CWriter::Write(const Block& block) {
32633280
}
32643281

32653282
size_t CWriter::BeginTry(const Block& block) {
3283+
func_includes_.insert("exceptions");
32663284
Write(OpenBrace()); /* beginning of try-catch or try_table */
32673285
const std::string tlabel = DefineLabelName(block.label);
32683286
Write("WASM_RT_UNWIND_TARGET *", tlabel,

0 commit comments

Comments
 (0)