diff options
Diffstat (limited to 'sqlite3-select-opencl.c')
-rw-r--r-- | sqlite3-select-opencl.c | 476 |
1 files changed, 476 insertions, 0 deletions
diff --git a/sqlite3-select-opencl.c b/sqlite3-select-opencl.c new file mode 100644 index 0000000..11ff14f --- /dev/null +++ b/sqlite3-select-opencl.c @@ -0,0 +1,476 @@ + +/* this module is included into the mass that has sqlite3.c before it + * as parse.h which is output by lemon is extremely important so that + * we can make use of the token definitions TK_* + * These define a variety of operators + */ + +int stringToType(char *typeByString) { + if (strcmp("INTEGER",typeByString) == 0) + return SQCL_INT; + else if (strcmp("REAL",typeByString) == 0) + return SQCL_FLOAT; +/* else if (strcmp("TEXT",typeByString) == 0) + return OPENCL_DOUBLE; + else if (strcmp("BLOB",typeByString) == 0) + return OPENCL_; */ + + return -1; // eh what? +} + +/* +** Generate code for the SELECT statement given in the p argument. +** +** The results are distributed in various ways depending on the +** contents of the SelectDest structure pointed to by argument pDest +** as follows: +** +** pDest->eDest Result +** ------------ ------------------------------------------- +** SRT_Output Generate a row of output (using the OP_ResultRow +** opcode) for each row in the result set. +** +** SRT_Mem Only valid if the result is a single column. +** Store the first column of the first result row +** in register pDest->iSDParm then abandon the rest +** of the query. This destination implies "LIMIT 1". +** +** SRT_Set The result must be a single column. Store each +** row of result as the key in table pDest->iSDParm. +** Apply the affinity pDest->affSdst before storing +** results. Used to implement "IN (SELECT ...)". +** +** SRT_Union Store results as a key in a temporary table +** identified by pDest->iSDParm. +** +** SRT_Except Remove results from the temporary table pDest->iSDParm. +** +** SRT_Table Store results in temporary table pDest->iSDParm. +** This is like SRT_EphemTab except that the table +** is assumed to already be open. +** +** SRT_EphemTab Create an temporary table pDest->iSDParm and store +** the result there. The cursor is left open after +** returning. This is like SRT_Table except that +** this destination uses OP_OpenEphemeral to create +** the table first. +** +** SRT_Coroutine Generate a co-routine that returns a new row of +** results each time it is invoked. The entry point +** of the co-routine is stored in register pDest->iSDParm. +** +** SRT_Exists Store a 1 in memory cell pDest->iSDParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. This is used by SELECT +** statements within triggers whose only purpose is +** the side-effects of functions. +** +** This routine returns the number of errors. If any errors are +** encountered, then an appropriate error message is left in +** pParse->zErrMsg. +** +** This routine does NOT free the Select structure passed in. The +** calling function needs to do that. +* 103174 +*/ + +/* +pNew->pSrc = pSrc; + pNew->pWhere = pWhere; + pNew->pGroupBy = pGroupBy; + pNew->pHaving = pHaving; + pNew->pOrderBy = pOrderBy; + pNew->selFlags = selFlags; + pNew->op = TK_SELECT; + pNew->pLimit = pLimit; + pNew->pOffset = pOffset; + assert( pOffset==0 || pLimit!=0 ); + pNew->addrOpenEphm[0] = -1; + pNew->addrOpenEphm[1] = -1; + pNew->addrOpenEphm[2] = -1; + */ +/* For now output to a file */ + +struct sqcl_variable { + int data_type; + int memory_type; + int columnNumber; + int used; + char name[20]; +}; + +typedef struct sqcl_variable sqcl_variable; + +struct fnentrypoint { + sqcl_variable *totalRows; + sqcl_variable *parameters; + sqcl_variable *temps; + int parameter_count; + char name[20]; + sqcl_variable *return_parameter; +}; + +typedef struct fnentrypoint fnentrypoint; + +// variable store + +int emit_cl_cl_memory_type(FILE *clOutputFile, int mem_type) { + switch(mem_type) { + case OPENCL_GLOBAL_MEMORY: + fprintf(clOutputFile,"__global "); + break; + case OPENCL_LOCAL_MEMORY: + fprintf(clOutputFile,"__local "); + break; + case OPENCL_CONSTANT_MEMORY: + fprintf(clOutputFile,"__constant "); + break; + case OPENCL_PRIVATE_MEMORY: + default: + fprintf(clOutputFile,"__private "); + break; + } + return 0; +} + +int emit_cl_data_type(FILE *clOutputFile, int var_type) { + switch(var_type) { + case SQCL_INT: + fprintf(clOutputFile,"int "); + break; + case SQCL_INT4: + fprintf(clOutputFile,"int4 "); + break; + case SQCL_INTPTR: + fprintf(clOutputFile,"int * "); + break; + case SQCL_FLOAT: + fprintf(clOutputFile,"float "); + break; + case SQCL_FLOAT4: + fprintf(clOutputFile,"float4 "); + break; + case SQCL_FLOATPTR: + fprintf(clOutputFile,"float * "); + break; + default: + break; + } + + return 0; +} + +int emit_cl_vector_load(FILE *clOutputFile, sqcl_variable *in, sqcl_variable *intmp) { + + fprintf(clOutputFile, "%s = vload4(0, %s + offset);\n", intmp->name, in->name ); + + return 0; +} +int emit_cl_vector_result_store(FILE *clOutputFile, sqcl_variable *tmp_result, sqcl_variable * result) { + + fprintf(clOutputFile, "vstore4(%s, 0, %s + offset);\n", tmp_result->name, result->name); + return 0; +} + +int descend_expr_tree(FILE *clOutputFile, Expr *scout) { + int err; + char buffer[64]; + switch (scout-> op) { + case TK_AND: + fprintf(clOutputFile,"("); + sprintf(buffer," && "); + break; + case TK_OR: + fprintf(clOutputFile,"("); + sprintf(buffer," || "); + break; + case TK_NE: + fprintf(clOutputFile,"("); + sprintf(buffer," != "); + break; + case TK_EQ: + fprintf(clOutputFile,"("); + sprintf(buffer," == "); + break; + case TK_GT: + fprintf(clOutputFile,"("); + sprintf(buffer," > "); + break; + case TK_GE: + fprintf(clOutputFile,"("); + sprintf(buffer," >= "); + break; + case TK_LT: + fprintf(clOutputFile,"("); + sprintf(buffer," < "); + break; + case TK_LE: + fprintf(clOutputFile,"("); + sprintf(buffer," <= "); + break; + case TK_INTEGER: + sprintf(buffer," %d ", scout->u.iValue); + break; +// case TK_FLOAT: +// fprintf(clOutputFile," %f ", scou); +// break; + case TK_COLUMN: + sprintf(buffer," %s ", scout->u.zToken); + break; + default: + return -1; + break; + } + // process + if (scout->pLeft) { + err=descend_expr_tree(clOutputFile, scout->pLeft); + if (err) { + return err; + } + } + + // emit + fprintf(clOutputFile, "%s",buffer); + + if (scout->pRight) { + err = descend_expr_tree(clOutputFile, scout->pRight); + if (err) { + return err; + } + } + + switch (scout-> op) { + case TK_AND: + fprintf(clOutputFile,")"); + break; + case TK_OR: + fprintf(clOutputFile,")"); + break; + case TK_NE: + fprintf(clOutputFile,")"); + break; + case TK_EQ: + fprintf(clOutputFile,")"); + break; + case TK_GT: + fprintf(clOutputFile,")"); + break; + case TK_GE: + fprintf(clOutputFile,")"); + break; + case TK_LT: + fprintf(clOutputFile,")"); + break; + case TK_LE: + fprintf(clOutputFile,")"); + break; + case TK_INTEGER: +// case TK_FLOAT: +// fprintf(clOutputFile," %f ", scou); +// break; + case TK_COLUMN: + default: + return -1; + break; + } + + return 0; +} + +int parse_and_emit_cl_operation(FILE *clOutputFile, Select *s,fnentrypoint *fn) { + + Expr *scout; + int err; + + fprintf(clOutputFile, "%s = ", fn->temps[fn->parameter_count].name); + + // walk WHERE expression + scout = s->pWhere; + err = descend_expr_tree(clOutputFile, scout); + fprintf(clOutputFile, ";\n"); + + return err; +} + +int emit_cl_fn(FILE *clOutputFile, fnentrypoint *fn, Select *s, SelectDest *sd) { + int i, err; + + fprintf(clOutputFile, "__kernel void %s (", fn->name); + + emit_cl_cl_memory_type(clOutputFile, fn->totalRows->memory_type); + emit_cl_data_type(clOutputFile, fn->totalRows->data_type); + + fprintf(clOutputFile,"%s,", fn->totalRows->name); + + sqcl_variable *q, *p = fn->parameters; + + for (i=0; i < fn->parameter_count; i++) { + + if (p->used) { + emit_cl_cl_memory_type(clOutputFile, p->memory_type); + emit_cl_data_type(clOutputFile, p->data_type); + + fprintf(clOutputFile,"%s", p->name); + } + p++; + fprintf(clOutputFile,", "); + } + + // last param is the resultMask + emit_cl_cl_memory_type(clOutputFile, fn->return_parameter->memory_type); + emit_cl_data_type(clOutputFile, fn->return_parameter->data_type); + + fprintf(clOutputFile,"%s", fn->return_parameter->name); + + fprintf(clOutputFile, ") {\n"); + + + // emit boiler plate + fprintf(clOutputFile, "\n"); + + // the last temp is used for per row results + p = fn->temps; + for(i=0; i<=fn->parameter_count; i++ ) { + if (p->used) { + emit_cl_cl_memory_type(clOutputFile, p->memory_type); + emit_cl_data_type(clOutputFile, p->data_type); + + fprintf(clOutputFile,"%s;\n", p->name); + } + p++; + } + + // emit global id info + fprintf(clOutputFile,"int i = get_global_id(0);\n"); + fprintf(clOutputFile,"size_t offset = i * (totalRows/workUnits);\n"); + + // start while + fprintf(clOutputFile,"do {\n"); + + // emit vector loads + q = fn->temps; + p = fn->parameters; + + for(i=0; i<fn->parameter_count; i++ ) { + emit_cl_vector_load(clOutputFile, p, q); + p++; + q++; + } + + // emit where test + err = parse_and_emit_cl_operation(clOutputFile, s, fn); + if (err) + return err; + + // emit vector store + emit_cl_vector_result_store(clOutputFile, &(fn->temps[fn->parameter_count]), fn->return_parameter); + + // emit decrement && vector walk + fprintf(clOutputFile,"\toffset+=4\n\ttotalRows--;\n"); + + // emit end while + fprintf(clOutputFile,"} while(totalRows);\n"); + + fprintf(clOutputFile, "}\n"); + + return 0; +} + +int sqlite3OpenCLSelect(Parse *p, Select *s, SelectDest *sd) { + + int i, err; + FILE *clOutputFile; + fnentrypoint mainFn; + + if (sqlite3AuthCheck(p, SQLITE_SELECT, 0, 0, 0) ) return 1; + + strcpy(mainFn.name, "x2_entry\0"); + + mainFn.parameters=NULL; + mainFn.parameter_count=0; + mainFn.return_parameter = NULL; + mainFn.totalRows = malloc (sizeof(sqcl_variable)); + mainFn.totalRows->data_type = SQCL_INT; + mainFn.totalRows->memory_type = OPENCL_GLOBAL_MEMORY; + mainFn.totalRows->columnNumber = -1; + mainFn.totalRows->used = 1; + strncpy(mainFn.totalRows->name, "totalRows\0",10); + + // nExpr appears to be the number of vars used in the select + mainFn.parameters = malloc ((sizeof(sqcl_variable)) * (s->pEList->nExpr)); + mainFn.temps = malloc ((sizeof(sqcl_variable)) * (s->pEList->nExpr +1) ); + + // last temp is for collecting results + mainFn.temps[s->pEList->nExpr].data_type = SQCL_INT4; + mainFn.temps[s->pEList->nExpr].memory_type = OPENCL_PRIVATE_MEMORY; + mainFn.temps[s->pEList->nExpr].columnNumber = -1; + mainFn.temps[s->pEList->nExpr].used = 1; + strncpy(mainFn.temps[s->pEList->nExpr].name, "_cl_r\0",6); + + + // return_parameter is a data structure that's passed in as a global + // that the results of the vector operation is stored into + mainFn.return_parameter = malloc (sizeof(sqcl_variable)); + mainFn.return_parameter->data_type = SQCL_INTPTR; + mainFn.return_parameter->memory_type = OPENCL_GLOBAL_MEMORY; + mainFn.return_parameter->columnNumber = -1; + mainFn.return_parameter->used = 1; + strncpy(mainFn.return_parameter->name, "_cl_resultMask\0",15); + + for (i = 0; i < s->pEList->nExpr; i++) { + if (s->pEList->a[i].pExpr->op == TK_COLUMN) { + mainFn.parameters[i].columnNumber = s->pEList->a[i].pExpr->iColumn; + mainFn.temps[i].columnNumber = s->pEList->a[i].pExpr->iColumn; + if (mainFn.parameters[i].columnNumber == -1 ) { + mainFn.parameters[i].columnNumber = 0; + mainFn.temps[i].columnNumber = 0; + } + + mainFn.parameters[i].data_type = stringToType(s->pEList->a[i].pExpr->pTab->aCol[mainFn.parameters[i].columnNumber].zType); + switch (mainFn.parameters[i].data_type) { + case SQCL_INT: + mainFn.parameters[i].data_type = SQCL_INTPTR; + mainFn.temps[i].data_type = SQCL_INT4; + break; + case SQCL_FLOAT: + mainFn.parameters[i].data_type = SQCL_FLOATPTR; + mainFn.temps[i].data_type = SQCL_FLOAT4; + break; + case -1: + // data type we can't handle yet. bail! + goto cleanAndFail; + } + mainFn.parameters[i].memory_type = OPENCL_GLOBAL_MEMORY; + mainFn.temps[i].memory_type = OPENCL_PRIVATE_MEMORY; + strncpy(mainFn.parameters[i].name, s->pEList->a[i].pExpr->u.zToken,20); + sprintf(mainFn.temps[i].name, "_cl_v%d\0", i); + mainFn.parameters[i].name[19]='\0'; + mainFn.parameter_count++; + mainFn.parameters[i].used = 1; + mainFn.temps[i].used = 1; + } else { + goto cleanAndFail; + } + } + + clOutputFile=fopen("machinegen-opencl/foo.cl", "w"); + + err = emit_cl_fn(clOutputFile, &mainFn, s, sd); + + fclose(clOutputFile); + + free(mainFn.parameters); + free(mainFn.temps); + free(mainFn.return_parameter); + free(mainFn.totalRows); + + return err; + +cleanAndFail: + free(mainFn.parameters); + free(mainFn.temps); + free(mainFn.return_parameter); + free(mainFn.totalRows); + return -1; +} |