static int sameSignature(rpmTagVal sigtag, Header h1, Header h2) { pgpDigParams sig1 = getSig(h1, sigtag); pgpDigParams sig2 = getSig(h2, sigtag);; int rc = pgpDigParamsCmp(sig1, sig2); pgpDigParamsFree(sig1); pgpDigParamsFree(sig2); return (rc == 0); }
void optimizeFunctionTypes(Module* module) { FunctionTypeAnalyzer analyzer; analyzer.walkModule(module); // maps each string signature to a single canonical function type std::unordered_map<std::string, FunctionType*> canonicals; std::unordered_set<FunctionType*> needed; auto canonicalize = [&](Name name) { if (!name.is()) return name; FunctionType* type = module->getFunctionType(name); auto sig = getSig(type); auto iter = canonicals.find(sig); if (iter == canonicals.end()) { needed.insert(type); canonicals[sig] = type; return type->name; } else { return iter->second->name; } }; // canonicalize all uses of function types for (auto* import : analyzer.functionImports) { import->type = canonicalize(import->type); } for (auto* func : analyzer.functions) { func->type = canonicalize(func->type); } for (auto* call : analyzer.indirectCalls) { call->fullType = canonicalize(call->fullType); } // remove no-longer used types module->functionTypes.erase(std::remove_if(module->functionTypes.begin(), module->functionTypes.end(), [&needed](std::unique_ptr<FunctionType>& type) { return needed.count(type.get()) == 0; }), module->functionTypes.end()); module->updateMaps(); }
std::vector<Function*> makeDynCallThunks(Module& wasm, std::vector<Name> const& tableSegmentData) { wasm.removeImport(EMSCRIPTEN_ASM_CONST); // we create _sig versions std::vector<Function*> generatedFunctions; std::unordered_set<std::string> sigs; Builder wasmBuilder(wasm); for (const auto& indirectFunc : tableSegmentData) { std::string sig(getSig(wasm.getFunction(indirectFunc))); auto* funcType = ensureFunctionType(sig, &wasm); if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. if (!sigs.insert(sig).second) continue; // Sig is already in the set std::vector<NameType> params; params.emplace_back("fptr", i32); // function pointer param int p = 0; for (const auto& ty : funcType->params) params.emplace_back(std::to_string(p++), ty); Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {}); Expression* fptr = wasmBuilder.makeGetLocal(0, i32); std::vector<Expression*> args; for (unsigned i = 0; i < funcType->params.size(); ++i) { args.push_back(wasmBuilder.makeGetLocal(i + 1, funcType->params[i])); } Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, args); f->body = call; wasm.addFunction(f); generatedFunctions.push_back(f); } return generatedFunctions; }
LogProb getProb(const F& f, const X& x) const { if (!mU.contains(x)) const_cast<SimpleMap<X,X>&>(mU).set(x) = getSig(f,x); X unkx = mU.get(x); if(!get(f).contains(x)) { return get(f).get(unkx); } else { return get(f).get(x) + get(f).get(unkx); } }
// Get multiple layers of a Benes permutation network. Returns in out[i][j] // the shift amount to move item j in the i'th layer. Also isID[i]=true if // the i'th layer is the identity (i.e., contains only 0 shift amounts). void ColPerm::getBenesShiftAmounts(Vec<Permut>& out, Vec<bool>& isID, const Vec<long>& benesLvls) const { // Go over the columns one by one. For each column extract the columns // permutation, prepare a Benes network for it, and then for every layer // compute the shift amounts for this columns. long n = getDim(dim); // the permutations are over [0,n-1] // Allocate space out.SetLength(benesLvls.length()); isID.SetLength(benesLvls.length()); for (long k=0; k<benesLvls.length(); k++) { out[k].SetLength(getSize()); isID[k] = true; } Vec<long> col; col.SetLength(n); for (long slice_index = 0; slice_index < numSlices(dim); slice_index++) { ConstCubeSlice<long> slice(*this, slice_index, dim); for (long col_index = 0; col_index < slice.numCols(); col_index++) { getHyperColumn(col, slice, col_index); GeneralBenesNetwork net(col); // build a Benes network for this column // Sanity checks: width of network == n, // and sum of benesLvls entries == # of levels assert(net.getSize()==n); {long sum=0; for (long k=0; k<benesLvls.length(); k++) sum+=benesLvls[k]; assert(net.getNumLevels()==sum); } // Compute the layers of the collapased network for this column for (long lvl=0,k=0; k<benesLvls.length(); lvl += benesLvls[k], k++) { // Returns in col the shift amounts for this layer in the network, // restricted to this column. Also returns true if the returned // permutation is the idendity, false otherwise. bool id = collapseBenesLevels(col, net, lvl, benesLvls[k]); isID[k] = isID[k] && id; CubeSlice<long> oslice(out[k], getSig()); CubeSlice<long> osubslice(oslice, slice_index, dim); setHyperColumn(col, osubslice, col_index); } // next collapsed layer } // next column } // next slice }
void AsmConstWalker::visitCallImport(CallImport* curr) { if (curr->target == EMSCRIPTEN_ASM_CONST) { auto arg = curr->operands[0]->cast<Const>(); auto address = arg->value.geti32(); auto segmentIterator = segmentsByAddress.find(address); std::string code; if (segmentIterator != segmentsByAddress.end()) { Address segmentIndex = segmentsByAddress[address]; code = escape(&wasm.memory.segments[segmentIndex].data[0]); } else { // If we can't find the segment corresponding with the address, then we omitted the segment and the address points to an empty string. code = escape(""); } int32_t id; if (ids.count(code) == 0) { id = ids.size(); ids[code] = id; } else { id = ids[code]; } std::string sig = getSig(curr); sigsForCode[code].insert(sig); std::string fixedTarget = EMSCRIPTEN_ASM_CONST.str + std::string("_") + sig; curr->target = cashew::IString(fixedTarget.c_str(), false); arg->value = Literal(id); // add import, if necessary if (allSigs.count(sig) == 0) { allSigs.insert(sig); auto import = new Import; import->name = import->base = curr->target; import->module = ENV; import->functionType = ensureFunctionType(getSig(curr), &wasm); import->kind = ExternalKind::Function; wasm.addImport(import); } } }