unique_ptr<HWLMProto> hwlmBuildProto(vector<hwlmLiteral> &lits, bool make_small, const CompileContext &cc) { assert(!lits.empty()); dumpLits(lits); // Check that we haven't exceeded the maximum number of literals. if (lits.size() > cc.grey.limitLiteralCount) { throw ResourceLimitError(); } // Safety and resource limit checks. u64a total_chars = 0; for (const auto &lit : lits) { assert(!lit.s.empty()); if (lit.s.length() > cc.grey.limitLiteralLength) { throw ResourceLimitError(); } total_chars += lit.s.length(); if (total_chars > cc.grey.limitLiteralMatcherChars) { throw ResourceLimitError(); } // We do not allow the all-ones ID, as we reserve that for internal use // within literal matchers. if (lit.id == 0xffffffffu) { assert(!"reserved id 0xffffffff used"); throw CompileError("Internal error."); } } unique_ptr<HWLMProto> proto; DEBUG_PRINTF("building table with %zu strings\n", lits.size()); assert(everyoneHasGroups(lits)); if (isNoodleable(lits, cc)) { DEBUG_PRINTF("build noodle table\n"); proto = ue2::make_unique<HWLMProto>(HWLM_ENGINE_NOOD, lits); } else { DEBUG_PRINTF("building a new deal\n"); proto = fdrBuildProto(HWLM_ENGINE_FDR, lits, make_small, cc.target_info, cc.grey); if (!proto) { return nullptr; } } return proto; }
void compile(void) { LEXEME *lex = NULL ; SetGlobalFlag(TRUE); helpinit(); errorinit(); constoptinit(); declare_init(); init_init(); inlineinit(); lambda_init(); rtti_init(); expr_init(); libcxx_init(); statement_ini(); syminit(); preprocini(infile, inputFile); lexini(); setglbdefs(); templateInit(); #ifndef PARSER_ONLY SSAInit(); outcodeini(); conflictini(); iexpr_init(); iinlineInit(); flow_init(); genstmtini(); #endif ParseBuiltins(); if (chosenAssembler->intrinsicInit) chosenAssembler->intrinsicInit(); if (chosenAssembler->inlineAsmInit) chosenAssembler->inlineAsmInit(); if (chosenAssembler->outcode_init) chosenAssembler->outcode_init(); if (chosenAssembler->enter_filename) chosenAssembler->enter_filename(clist->data); if (cparams.prm_debug && chosenDebugger && chosenDebugger->init) chosenDebugger->init(); if (cparams.prm_browse && chosenDebugger && chosenDebugger->init_browsedata) chosenDebugger->init_browsedata(clist->data); browse_init(); browse_startfile(infile, 0); if (cparams.prm_assemble) { lex = getsym(); if (lex) { BLOCKDATA block; memset(&block, 0, sizeof(block)); block.type = begin; while ((lex = statement_asm(lex, NULL, &block)) != NULL) ; #ifndef PARSER_ONLY genASM(block.head); #endif } } else { #ifndef PARSER_ONLY asm_header(clist->data, version); #endif lex = getsym(); if (lex) { while ((lex = declare(lex, NULL, NULL, sc_global, lk_none, NULL, TRUE, FALSE, FALSE, FALSE, ac_public)) != NULL) ; } } #ifdef PARSER_ONLY ccDumpSymbols(); #endif if (!total_errors) { dumpInlines(); dumpInitializers(); dumpInlines(); dumpStartups(); #ifndef PARSER_ONLY dumpLits(); #endif /* rewrite_icode(); */ if (chosenAssembler->gen->finalGen) chosenAssembler->gen->finalGen(); if (!cparams.prm_assemble && cparams.prm_debug) if (chosenDebugger && chosenDebugger->outputtypedef) debug_dumptypedefs(globalNameSpace); #ifndef PARSER_ONLY putexterns(); #endif if (!cparams.prm_asmfile) if (chosenAssembler->output_obj_file) chosenAssembler->output_obj_file(); } findUnusedStatics(globalNameSpace); dumperrs(stdout); if (cparams.prm_debug && chosenDebugger && chosenDebugger->rundown) chosenDebugger->rundown(); if (cparams.prm_browse && chosenDebugger && chosenDebugger->rundown_browsedata) chosenDebugger->rundown_browsedata(); #ifndef PARSER_ONLY if (!cparams.prm_assemble) asm_trailer(); #endif }
aligned_unique_ptr<HWLM> hwlmBuild(const vector<hwlmLiteral> &lits, hwlmStreamingControl *stream_control, bool make_small, const CompileContext &cc, hwlm_group_t expected_groups) { assert(!lits.empty()); dumpLits(lits); if (stream_control) { assert(stream_control->history_min <= stream_control->history_max); } // Check that we haven't exceeded the maximum number of literals. if (lits.size() > cc.grey.limitLiteralCount) { throw ResourceLimitError(); } // Safety and resource limit checks. u64a total_chars = 0; for (const auto &lit : lits) { assert(!lit.s.empty()); if (lit.s.length() > cc.grey.limitLiteralLength) { throw ResourceLimitError(); } total_chars += lit.s.length(); if (total_chars > cc.grey.limitLiteralMatcherChars) { throw ResourceLimitError(); } // We do not allow the all-ones ID, as we reserve that for internal use // within literal matchers. if (lit.id == 0xffffffffu) { assert(!"reserved id 0xffffffff used"); throw CompileError("Internal error."); } } u8 engType = 0; size_t engSize = 0; shared_ptr<void> eng; DEBUG_PRINTF("building table with %zu strings\n", lits.size()); assert(everyoneHasGroups(lits)); if (isNoodleable(lits, stream_control, cc)) { DEBUG_PRINTF("build noodle table\n"); engType = HWLM_ENGINE_NOOD; const hwlmLiteral &lit = lits.front(); auto noodle = noodBuildTable((const u8 *)lit.s.c_str(), lit.s.length(), lit.nocase, lit.id); if (noodle) { engSize = noodSize(noodle.get()); } if (stream_control) { // For now, a single literal still goes to noodle and asks // for a great big history stream_control->literal_history_required = lit.s.length() - 1; assert(stream_control->literal_history_required <= stream_control->history_max); stream_control->literal_stream_state_required = 0; } eng = move(noodle); } else { DEBUG_PRINTF("building a new deal\n"); engType = HWLM_ENGINE_FDR; auto fdr = fdrBuildTable(lits, make_small, cc.target_info, cc.grey, stream_control); if (fdr) { engSize = fdrSize(fdr.get()); } eng = move(fdr); } if (!eng) { return nullptr; } assert(engSize); if (engSize > cc.grey.limitLiteralMatcherSize) { throw ResourceLimitError(); } auto h = aligned_zmalloc_unique<HWLM>(ROUNDUP_CL(sizeof(HWLM)) + engSize); h->type = engType; memcpy(HWLM_DATA(h.get()), eng.get(), engSize); if (engType == HWLM_ENGINE_FDR && cc.grey.hamsterAccelForward) { buildForwardAccel(h.get(), lits, expected_groups); } if (stream_control) { DEBUG_PRINTF("requires %zu (of max %zu) bytes of history\n", stream_control->literal_history_required, stream_control->history_max); assert(stream_control->literal_history_required <= stream_control->history_max); } return h; }