int main(int argc, char **argv) { /* Test Crash in simple test is reported */ simple = true; runa=false; runc=false; igt_info("Simple test.\n"); fflush(stdout); internal_assert(do_fork() == SIGSEGV + 128); /* Test crash in a single subtest is reported */ simple = false; igt_info("Single subtest.\n"); fflush(stdout); internal_assert(do_fork() == SIGSEGV + 128); /* Test crash in a subtest following a pass is reported */ simple = false; runa=true; igt_info("Passing then crashing subtest.\n"); fflush(stdout); internal_assert(do_fork() == SIGSEGV + 128); /* Test crash in a subtest preceeding a pass is reported */ simple = false; runa=false; runc=true; igt_info("Crashing then passing subtest.\n"); fflush(stdout); internal_assert(do_fork() == SIGSEGV + 128); return 0; }
Schedule Schedule::deep_copy( std::map<IntrusivePtr<FunctionContents>, IntrusivePtr<FunctionContents>> &copied_map) const { internal_assert(contents.defined()) << "Cannot deep-copy undefined Schedule\n"; Schedule copy; copy.contents->store_level = contents->store_level; copy.contents->compute_level = contents->compute_level; copy.contents->rvars = contents->rvars; copy.contents->splits = contents->splits; copy.contents->dims = contents->dims; copy.contents->storage_dims = contents->storage_dims; copy.contents->bounds = contents->bounds; copy.contents->memoized = contents->memoized; copy.contents->touched = contents->touched; copy.contents->allow_race_conditions = contents->allow_race_conditions; // Deep-copy wrapper functions. If function has already been deep-copied before, // i.e. it's in the 'copied_map', use the deep-copied version from the map instead // of creating a new deep-copy for (const auto &iter : contents->wrappers) { IntrusivePtr<FunctionContents> &copied_func = copied_map[iter.second]; if (copied_func.defined()) { copy.contents->wrappers[iter.first] = copied_func; } else { copy.contents->wrappers[iter.first] = deep_copy_function_contents_helper(iter.second, copied_map); copied_map[iter.second] = copy.contents->wrappers[iter.first]; } } internal_assert(copy.contents->wrappers.size() == contents->wrappers.size()); return copy; }
void CodeGen_GPU_Host<CodeGen_CPU>::jit_finalize(ExecutionEngine *ee, Module *module, vector<JITCompiledModule::CleanupRoutine> *cleanup_routines) { if (target.features & Target::CUDA) { // Remap the cuda_ctx of PTX host modules to a shared location for all instances. // CUDA behaves much better when you don't initialize >2 contexts. llvm::Function *fn = module->getFunction("halide_set_cuda_context"); internal_assert(fn) << "Could not find halide_set_cuda_context in module\n"; void *f = ee->getPointerToFunction(fn); internal_assert(f) << "Could not find compiled form of halide_set_cuda_context in module\n"; void (*set_cuda_context)(CUcontext *, volatile int *) = reinterpret_bits<void (*)(CUcontext *, volatile int *)>(f); set_cuda_context(&cuda_ctx.ptr, &cuda_ctx.lock); } else if (target.features & Target::OpenCL) { // Share the same cl_ctx, cl_q across all OpenCL modules. llvm::Function *fn = module->getFunction("halide_set_cl_context"); internal_assert(fn) << "Could not find halide_set_cl_context in module\n"; void *f = ee->getPointerToFunction(fn); internal_assert(f) << "Could not find compiled form of halide_set_cl_context in module\n"; void (*set_cl_context)(cl_context *, cl_command_queue *, volatile int *) = reinterpret_bits<void (*)(cl_context *, cl_command_queue *, volatile int *)>(f); set_cl_context(&cl_ctx.context, &cl_ctx.command_queue, &cl_ctx.lock); } // If the module contains a halide_release function, run it when the module dies. llvm::Function *fn = module->getFunction("halide_release"); if (fn) { void *f = ee->getPointerToFunction(fn); internal_assert(f) << "Could not find compiled form of halide_release in module\n"; void (*cleanup_routine)(void *) = reinterpret_bits<void (*)(void *)>(f); cleanup_routines->push_back(JITCompiledModule::CleanupRoutine(cleanup_routine, NULL)); } }
Definition get_stage_definition(const Function &f, int stage_num) { internal_assert(!f.has_extern_definition()); if (stage_num == 0) { return f.definition(); } internal_assert((int)f.updates().size() >= stage_num); return f.update(stage_num - 1); }
void dir_rmdir(const std::string &name) { #ifdef _MSC_VER BOOL r = RemoveDirectoryA(name.c_str()); internal_assert(r != 0) << "Unable to remove dir: " << name << ":" << GetLastError() << "\n"; #else int r = ::rmdir(name.c_str()); internal_assert(r == 0) << "Unable to remove dir: " << name << "\n"; #endif }
Stmt AssertStmt::make(Expr condition, Expr message) { internal_assert(condition.defined()) << "AssertStmt of undefined\n"; internal_assert(message.type() == Int(32)) << "AssertStmt message must be an int:" << message << "\n"; AssertStmt *node = new AssertStmt; node->condition = condition; node->message = message; return node; }
Expr Not::make(Expr a) { internal_assert(a.defined()) << "Not of undefined\n"; internal_assert(a.type().is_bool()) << "argument of Not is not a bool\n"; Not *node = new Not; node->type = Bool(a.type().width); node->a = a; return node; }
Expr Cast::make(Type t, Expr v) { internal_assert(v.defined()) << "Cast of undefined\n"; internal_assert(t.width == v.type().width) << "Cast may not change vector widths\n"; Cast *node = new Cast; node->type = t; node->value = v; return node; }
Stmt Store::make(std::string name, Expr value, Expr index) { internal_assert(value.defined()) << "Store of undefined\n"; internal_assert(index.defined()) << "Store of undefined\n"; Store *node = new Store; node->name = name; node->value = value; node->index = index; return node; }
Stmt LetStmt::make(std::string name, Expr value, Stmt body) { internal_assert(value.defined()) << "Let of undefined\n"; internal_assert(body.defined()) << "Let of undefined\n"; LetStmt *node = new LetStmt; node->name = name; node->value = value; node->body = body; return node; }
Expr Broadcast::make(Expr value, int width) { internal_assert(value.defined()) << "Broadcast of undefined\n"; internal_assert(value.type().is_scalar()) << "Broadcast of vector\n"; internal_assert(width != 1) << "Broadcast of width 1\n"; Broadcast *node = new Broadcast; node->type = value.type().vector_of(width); node->value = value; node->width = width; return node; }
Expr Mod::make(Expr a, Expr b) { internal_assert(a.defined()) << "Mod of undefined\n"; internal_assert(b.defined()) << "Mod of undefined\n"; internal_assert(a.type() == b.type()) << "Mod of mismatched types\n"; Mod *node = new Mod; node->type = a.type(); node->a = a; node->b = b; return node; }
Expr Sub::make(Expr a, Expr b) { internal_assert(a.defined()) << "Sub of undefined\n"; internal_assert(b.defined()) << "Sub of undefined\n"; internal_assert(a.type() == b.type()) << "Sub of mismatched types\n"; Sub *node = new Sub; node->type = a.type(); node->a = a; node->b = b; return node; }
Expr Div::make(Expr a, Expr b) { internal_assert(a.defined()) << "Div of undefined\n"; internal_assert(b.defined()) << "Div of undefined\n"; internal_assert(a.type() == b.type()) << "Div of mismatched types\n"; Div *node = new Div; node->type = a.type(); node->a = a; node->b = b; return node; }
Expr GE::make(Expr a, Expr b) { internal_assert(a.defined()) << "GE of undefined\n"; internal_assert(b.defined()) << "GE of undefined\n"; internal_assert(a.type() == b.type()) << "GE of mismatched types\n"; GE *node = new GE; node->type = Bool(a.type().width); node->a = a; node->b = b; return node; }
Expr Or::make(Expr a, Expr b) { internal_assert(a.defined()) << "Or of undefined\n"; internal_assert(b.defined()) << "Or of undefined\n"; internal_assert(a.type().is_bool()) << "lhs of Or is not a bool\n"; internal_assert(b.type().is_bool()) << "rhs of Or is not a bool\n"; Or *node = new Or; node->type = Bool(a.type().width); node->a = a; node->b = b; return node; }
Expr Load::make(Type type, std::string name, Expr index, Buffer image, Parameter param) { internal_assert(index.defined()) << "Load of undefined\n"; internal_assert(type.width == index.type().width) << "Vector width of Load must match vector width of index\n"; Load *node = new Load; node->type = type; node->name = name; node->index = index; node->image = image; node->param = param; return node; }
Stmt Pipeline::make(std::string name, Stmt produce, Stmt update, Stmt consume) { internal_assert(produce.defined()) << "Pipeline of undefined\n"; // update is allowed to be null internal_assert(consume.defined()) << "Pipeline of undefined\n"; Pipeline *node = new Pipeline; node->name = name; node->produce = produce; node->update = update; node->consume = consume; return node; }
Expr And::make(Expr a, Expr b) { internal_assert(a.defined()) << "And of undefined\n"; internal_assert(b.defined()) << "And of undefined\n"; internal_assert(a.type().is_bool()) << "lhs of And is not a bool\n"; internal_assert(b.type().is_bool()) << "rhs of And is not a bool\n"; And *node = new And; node->type = Bool(a.type().width); node->a = a; node->b = b; return node; }
void create_static_library(const std::vector<std::string> &src_files, const Target &target, const std::string &dst_file, bool deterministic) { internal_assert(!src_files.empty()); #if LLVM_VERSION >= 39 std::vector<llvm::NewArchiveMember> new_members; for (auto &src : src_files) { llvm::Expected<llvm::NewArchiveMember> new_member = llvm::NewArchiveMember::getFile(src, /*Deterministic=*/true); if (!new_member) { // Don't use internal_assert: the call to new_member.takeError() will be evaluated // even if the assert does not fail, leaving new_member in an indeterminate // state. internal_error << src << ": " << llvm::toString(new_member.takeError()) << "\n"; } new_members.push_back(std::move(*new_member)); } #elif LLVM_VERSION == 38 std::vector<llvm::NewArchiveIterator> new_members; for (auto &src : src_files) { new_members.push_back(llvm::NewArchiveIterator(src)); } #else std::vector<llvm::NewArchiveIterator> new_members; for (auto &src : src_files) { new_members.push_back(llvm::NewArchiveIterator(src, src)); } #endif const bool write_symtab = true; const auto kind = Internal::get_triple_for_target(target).isOSDarwin() ? llvm::object::Archive::K_BSD : llvm::object::Archive::K_GNU; #if LLVM_VERSION == 37 auto result = llvm::writeArchive(dst_file, new_members, write_symtab, kind, deterministic); #elif LLVM_VERSION == 38 const bool thin = false; auto result = llvm::writeArchive(dst_file, new_members, write_symtab, kind, deterministic, thin); #else const bool thin = false; auto result = llvm::writeArchive(dst_file, new_members, write_symtab, kind, deterministic, thin, nullptr); #endif internal_assert(!result.second) << "Failed to write archive: " << dst_file << ", reason: " << result.second << "\n"; }
ScheduleParamBase &ScheduleParamBase::operator=(const ScheduleParamBase &that) { if (this != &that) { // You can only assign SP's of the same type. internal_assert(type == that.type); // You can only assign SP's of the same name. internal_assert(sp_name == that.sp_name); sp_name = that.sp_name; type = that.type; scalar_parameter = that.scalar_parameter; scalar_expr = that.scalar_expr; loop_level = that.loop_level; } return *this; }
std::string dir_make_temp() { #ifdef _WIN32 char tmp_path[MAX_PATH]; DWORD ret = GetTempPathA(MAX_PATH, tmp_path); internal_assert(ret != 0); // There's no direct API to do this in Windows; // our clunky-but-adequate approach here is to use // CoCreateGuid() to create a probably-unique name. // Add a limit on the number of tries just in case. for (int tries = 0; tries < 100; ++tries) { GUID guid; HRESULT hr = CoCreateGuid(&guid); internal_assert(hr == S_OK); std::ostringstream name; name << std::hex << std::setfill('0') << std::setw(8) << guid.Data1 << std::setw(4) << guid.Data2 << guid.Data3 << std::setw(2); for (int i = 0; i < 8; i++) { name << (int)guid.Data4[i]; } std::string dir = std::string(tmp_path) + std::string(name.str()); BOOL result = CreateDirectoryA(dir.c_str(), nullptr); if (result) { debug(1) << "temp dir is: " << dir << "\n"; return dir; } // If name already existed, just loop and try again. // Any other error, break from loop and fail. if (GetLastError() != ERROR_ALREADY_EXISTS) { break; } } internal_assert(false) << "Unable to create temp directory.\n"; return ""; #else std::string templ = "/tmp/XXXXXX"; // Copy into a temporary buffer, since mkdtemp modifies the buffer in place. std::vector<char> buf(templ.size() + 1); strcpy(&buf[0], templ.c_str()); char* result = mkdtemp(&buf[0]); internal_assert(result != nullptr) << "Unable to create temp directory.\n"; return std::string(result); #endif }
Stmt Provide::make(std::string name, const std::vector<Expr> &values, const std::vector<Expr> &args) { internal_assert(!values.empty()) << "Provide of no values\n"; for (size_t i = 0; i < values.size(); i++) { internal_assert(values[i].defined()) << "Provide of undefined value\n"; } for (size_t i = 0; i < args.size(); i++) { internal_assert(args[i].defined()) << "Provide to undefined location\n"; } Provide *node = new Provide; node->name = name; node->values = values; node->args = args; return node; }
bool LoopLevel::match(const LoopLevel &other) const { internal_assert(defined()); return (contents->func_name == other.contents->func_name && (contents->var_name == other.contents->var_name || Internal::ends_with(contents->var_name, "." + other.contents->var_name) || Internal::ends_with(other.contents->var_name, "." + contents->var_name))); }
/* static */ void GeneratorRegistry::unregister_factory(const std::string &name) { GeneratorRegistry ®istry = get_registry(); std::lock_guard<std::mutex> lock(registry.mutex); internal_assert(registry.factories.find(name) != registry.factories.end()) << "Generator not found: " << name; registry.factories.erase(name); }
Parameter::Parameter(Type t, bool is_buffer, int d, const std::string &name, bool is_explicit_name, bool register_instance) : contents(new ParameterContents(t, is_buffer, d, name, is_explicit_name, register_instance)) { internal_assert(is_buffer || d == 0) << "Scalar parameters should be zero-dimensional"; if (contents.defined() && contents.ptr->is_registered) { ObjectInstanceRegistry::register_instance(this, 0, ObjectInstanceRegistry::FilterParam, this, NULL); } }
set<string> get_parents(Function f, int stage) { set<string> parents; if (f.has_extern_definition()) { internal_assert(stage == 0); for (const ExternFuncArgument &arg : f.extern_arguments()) { if (arg.is_func()) { string prod_name = Function(arg.func).name(); parents.insert(prod_name); } else if (arg.is_expr()) { FindAllCalls find; arg.expr.accept(&find); parents.insert(find.funcs_called.begin(), find.funcs_called.end()); } else if (arg.is_image_param() || arg.is_buffer()) { Buffer<> buf; if (arg.is_image_param()) { buf = arg.image_param.buffer(); } else { buf = arg.buffer; } parents.insert(buf.name()); } } } else { FindAllCalls find; Definition def = get_stage_definition(f, stage); def.accept(&find); parents.insert(find.funcs_called.begin(), find.funcs_called.end()); } return parents; }
Expr lower_euclidean_div(Expr a, Expr b) { internal_assert(a.type() == b.type()); // IROperator's div_round_to_zero will replace this with a / b for // unsigned ops, so create the intrinsic directly. Expr q = Call::make(a.type(), Call::div_round_to_zero, {a, b}, Call::PureIntrinsic); if (a.type().is_int()) { // Signed integer division sucks. It should be defined such // that it satisifies (a/b)*b + a%b = a, where 0 <= a%b < |b|, // i.e. Euclidean division. // We get rounding to work by examining the implied remainder // and correcting the quotient. /* Here's the C code that we're trying to match: int q = a / b; int r = a - q * b; int bs = b >> (t.bits() - 1); int rs = r >> (t.bits() - 1); return q - (rs & bs) + (rs & ~bs); */ Expr r = a - q*b; Expr bs = b >> (a.type().bits() - 1); Expr rs = r >> (a.type().bits() - 1); q = q - (rs & bs) + (rs & ~bs); return common_subexpression_elimination(q); } else {
Stmt Evaluate::make(Expr v) { internal_assert(v.defined()) << "Evaluate of undefined\n"; Evaluate *node = new Evaluate; node->value = v; return node; }
std::string file_make_temp(const std::string &prefix, const std::string &suffix) { internal_assert(prefix.find("/") == string::npos && prefix.find("\\") == string::npos && suffix.find("/") == string::npos && suffix.find("\\") == string::npos); #ifdef _WIN32 // Windows implementations of mkstemp() try to create the file in the root // directory, which is... problematic. char tmp_path[MAX_PATH], tmp_file[MAX_PATH]; DWORD ret = GetTempPathA(MAX_PATH, tmp_path); internal_assert(ret != 0); // Note that GetTempFileNameA() actually creates the file. ret = GetTempFileNameA(tmp_path, prefix.c_str(), 0, tmp_file); internal_assert(ret != 0); return std::string(tmp_file); #else std::string templ = "/tmp/" + prefix + "XXXXXX" + suffix; // Copy into a temporary buffer, since mkstemp modifies the buffer in place. std::vector<char> buf(templ.size() + 1); strcpy(&buf[0], templ.c_str()); int fd = mkstemps(&buf[0], suffix.size()); internal_assert(fd != -1) << "Unable to create temp file for (" << &buf[0] << ")\n"; close(fd); return std::string(&buf[0]); #endif }