Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit 0664495

Browse files
committed
declare types for functions which may not have a use, so that asm2wasm can infer their type (e.g. they may only be in a table, but never called)
1 parent 4a26fb3 commit 0664495

File tree

1 file changed

+51
-14
lines changed

1 file changed

+51
-14
lines changed

lib/Target/JSBackend/JSBackend.cpp

+51-14
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ namespace {
233233
BlockAddressMap BlockAddresses;
234234
std::map<std::string, AsmConstInfo> AsmConsts; // code => { index, list of seen sigs }
235235
NameSet FuncRelocatableExterns; // which externals are accessed in this function; we load them once at the beginning (avoids a potential call in a heap access, and might be faster)
236+
std::set<const Function*> DeclaresNeedingTypeDeclarations; // list of declared funcs whose type we must declare asm.js-style with a usage, as they may not have another usage
236237

237238
struct {
238239
// 0 is reserved for void type
@@ -434,6 +435,14 @@ namespace {
434435
(this->*(CH->second))(NULL, Name, -1);
435436
}
436437

438+
// and in asm.js, types are inferred from use. so if we have a method that *only* appears in a table, it therefore has no use,
439+
// and we are in trouble; emit a fake dce-able use for it.
440+
if (WebAssembly) {
441+
if (F->isDeclaration()) {
442+
DeclaresNeedingTypeDeclarations.insert(F);
443+
}
444+
}
445+
437446
return Index;
438447
}
439448

@@ -701,6 +710,7 @@ namespace {
701710
/// Like getPtrUse(), but for pointers represented in string expression form.
702711
static std::string getHeapAccess(const std::string& Name, unsigned Bytes, bool Integer=true);
703712

713+
std::string getUndefValue(Type* T, AsmCast sign=ASM_SIGNED);
704714
std::string getConstant(const Constant*, AsmCast sign=ASM_SIGNED);
705715
template<typename VectorType/*= ConstantVector or ConstantDataVector*/>
706716
std::string getConstantVector(const VectorType *C);
@@ -1464,6 +1474,23 @@ std::string JSWriter::getPtrUse(const Value* Ptr) {
14641474
return std::string(HeapName) + '[' + Index + ']';
14651475
}
14661476

1477+
std::string JSWriter::getUndefValue(Type* T, AsmCast sign) {
1478+
std::string S;
1479+
if (VectorType *VT = dyn_cast<VectorType>(T)) {
1480+
checkVectorType(VT);
1481+
S = std::string("SIMD_") + SIMDType(VT) + "_splat(" + ensureFloat("0", !VT->getElementType()->isIntegerTy()) + ')';
1482+
} else {
1483+
if (OnlyWebAssembly && T->isIntegerTy() && T->getIntegerBitWidth() == 64) {
1484+
return "i64(0)";
1485+
}
1486+
S = T->isFloatingPointTy() ? "+0" : "0"; // XXX refactor this
1487+
if (PreciseF32 && T->isFloatTy() && !(sign & ASM_FFI_OUT)) {
1488+
S = "Math_fround(" + S + ")";
1489+
}
1490+
}
1491+
return S;
1492+
}
1493+
14671494
std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) {
14681495
if (isa<ConstantPointerNull>(CV)) return "0";
14691496

@@ -1516,20 +1543,7 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) {
15161543
return emitI64Const(CI->getValue());
15171544
}
15181545
} else if (isa<UndefValue>(CV)) {
1519-
std::string S;
1520-
if (VectorType *VT = dyn_cast<VectorType>(CV->getType())) {
1521-
checkVectorType(VT);
1522-
S = std::string("SIMD_") + SIMDType(VT) + "_splat(" + ensureFloat("0", !VT->getElementType()->isIntegerTy()) + ')';
1523-
} else {
1524-
if (OnlyWebAssembly && CV->getType()->isIntegerTy() && CV->getType()->getIntegerBitWidth() == 64) {
1525-
return "i64(0)";
1526-
}
1527-
S = CV->getType()->isFloatingPointTy() ? "+0" : "0"; // XXX refactor this
1528-
if (PreciseF32 && CV->getType()->isFloatTy() && !(sign & ASM_FFI_OUT)) {
1529-
S = "Math_fround(" + S + ")";
1530-
}
1531-
}
1532-
return S;
1546+
return getUndefValue(CV->getType(), sign);
15331547
} else if (isa<ConstantAggregateZero>(CV)) {
15341548
if (VectorType *VT = dyn_cast<VectorType>(CV->getType())) {
15351549
checkVectorType(VT);
@@ -3397,6 +3411,29 @@ void JSWriter::printModuleBody() {
33973411
Out << "}\n";
33983412
Exports.push_back("__post_instantiate");
33993413
}
3414+
if (DeclaresNeedingTypeDeclarations.size() > 0) {
3415+
Out << "function __emscripten_dceable_type_decls() {\n";
3416+
for (auto& Decl : DeclaresNeedingTypeDeclarations) {
3417+
std::string Call = getJSName(Decl) + "(";
3418+
bool First = true;
3419+
auto* FT = Decl->getFunctionType();
3420+
for (auto AI = FT->param_begin(), AE = FT->param_end(); AI != AE; ++AI) {
3421+
if (First) {
3422+
First = false;
3423+
} else {
3424+
Call += ", ";
3425+
}
3426+
Call += getUndefValue(*AI);
3427+
}
3428+
Call += ")";
3429+
Type *RT = FT->getReturnType();
3430+
if (!RT->isVoidTy()) {
3431+
Call = getCast(Call, RT);
3432+
}
3433+
Out << " " << Call << ";\n";
3434+
}
3435+
Out << "}\n";
3436+
}
34003437
}
34013438
Out << "// EMSCRIPTEN_END_FUNCTIONS\n\n";
34023439

0 commit comments

Comments
 (0)