391 lines
15 KiB
C++
391 lines
15 KiB
C++
#include "dvm.h"
|
|
#include "acc_data.h"
|
|
#include "calls.h"
|
|
|
|
//TMP:
|
|
extern symb_list *acc_call_list, *by_value_list;
|
|
|
|
// create comments of call procedures from each kernel in file _info.c
|
|
// if -FTN_Cuda option selected
|
|
void ACC_RTC_AddCalledProcedureComment(SgSymbol *symbK)
|
|
{
|
|
symb_list *sl;
|
|
int len = 0;
|
|
for (sl = acc_call_list; sl; sl = sl->next)
|
|
len = len + strlen(sl->symb->identifier()) + 1;
|
|
|
|
char *list_txt = new char[len + 1];
|
|
list_txt[0] = '\0';
|
|
for (sl = acc_call_list; sl; sl = sl->next)
|
|
{
|
|
strcat(list_txt, " ");
|
|
strcat(list_txt, sl->symb->identifier());
|
|
}
|
|
info_block->addComment(CalledProcedureComment(list_txt, symbK));
|
|
|
|
}
|
|
|
|
// complete rtc launch parameters from cuda-handlers
|
|
void ACC_RTC_CompleteAllParams()
|
|
{
|
|
for (unsigned fc = 0; fc < RTC_FCall.size(); ++fc)
|
|
{
|
|
SgFunctionCallExp *fCall = RTC_FKernelArgs[fc];
|
|
if (fCall->variant() == EXPR_LIST) // if Fortran CUDA
|
|
{
|
|
fCall = new SgFunctionCallExp(*createNewFunctionSymbol(""));
|
|
SgExpression *tmp = RTC_FKernelArgs[fc];
|
|
while (tmp)
|
|
{
|
|
fCall->addArg(*tmp->lhs());
|
|
tmp = tmp->rhs();
|
|
}
|
|
}
|
|
|
|
SgExpression *argList = RTC_FArgs[fc];
|
|
for (int k = 0; k < fCall->numberOfArgs(); ++k)
|
|
{
|
|
SgExpression *currArg = fCall->arg(k);
|
|
bool dontCast = false;
|
|
|
|
if (currArg->variant() == DEREF_OP)
|
|
currArg = currArg->lhs();
|
|
|
|
if (currArg->symbol() == NULL)
|
|
{
|
|
RTC_FCall[fc]->addArg(*new SgValueExp("<!!! NULL !!!>"));
|
|
argList = argList->rhs();
|
|
continue;
|
|
}
|
|
std::string tmpN = currArg->symbol()->identifier();
|
|
bool isarray = isSgArrayType(currArg->symbol()->type());
|
|
bool ispointer = isSgPointerType(currArg->symbol()->type());
|
|
bool notbyval = true;
|
|
symb_list *sl;
|
|
for (sl = by_value_list; sl; sl = sl->next)
|
|
{
|
|
if (strcmp(sl->symb->identifier(), currArg->symbol()->identifier()) == 0)
|
|
{
|
|
notbyval = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
bool isinuser = isInUsesListByChar(currArg->symbol()->identifier());
|
|
if (isarray || ispointer || notbyval && isinuser)
|
|
{
|
|
RTC_FCall[fc]->addArg(*new SgValueExp(""));
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_POINTER")));
|
|
RTC_FCall[fc]->addArg(*argList->lhs());
|
|
}
|
|
else
|
|
{
|
|
SgType *tmp = currArg->symbol()->type();
|
|
|
|
if (tmp->hasBaseType())
|
|
tmp->baseType();
|
|
|
|
unsigned UnFlag = ((SgDescriptType*)tmp)->modifierFlag() & BIT_UNSIGNED;
|
|
|
|
SgAttribute *attr = argList->lhs()->getAttribute(0);
|
|
bool toAdd = false;
|
|
if (attr != NULL)
|
|
{
|
|
if (attr->getAttributeType() == RTC_NOT_REPLACE)
|
|
RTC_FCall[fc]->addArg(*new SgValueExp(""));
|
|
else
|
|
toAdd = true;
|
|
}
|
|
else
|
|
toAdd = true;
|
|
|
|
if (toAdd)
|
|
{
|
|
if (options.isOn(C_CUDA))
|
|
RTC_FCall[fc]->addArg(*new SgValueExp(currArg->symbol()->identifier()));
|
|
else
|
|
{
|
|
// PGI adds to scalars n__V_ !!
|
|
std::string tmp = "n__V_";
|
|
tmp += aks_strlowr(currArg->symbol()->identifier());
|
|
RTC_FCall[fc]->addArg(*new SgValueExp(tmp.c_str()));
|
|
}
|
|
}
|
|
|
|
if (tmp->equivalentToType(C_Type(SgTypeChar())) || tmp->equivalentToType(SgTypeChar()))
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UCHAR")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_CHAR")));
|
|
}
|
|
else if (tmp->equivalentToType(C_Type(SgTypeInt())) || (tmp->equivalentToType(SgTypeInt())))
|
|
{
|
|
if (isSgDescriptType(tmp))
|
|
{
|
|
SgDescriptType *t = (SgDescriptType*)tmp;
|
|
int flag = t->modifierFlag();
|
|
if ((flag & BIT_LONG) != 0)
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULONG")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
|
|
}
|
|
else if ((flag & BIT_SHORT) != 0)
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_USHORT")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_SHORT")));
|
|
}
|
|
else
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UINT")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UINT")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
|
|
}
|
|
}
|
|
else if (tmp->equivalentToType(C_LongType()))
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULONG")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
|
|
}
|
|
else if (tmp->equivalentToType(C_LongLongType()))
|
|
{
|
|
if (UnFlag)
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_ULLONG")));
|
|
else
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LLONG")));
|
|
}
|
|
else if (tmp->equivalentToType(C_Type(SgTypeFloat())) || tmp->equivalentToType(SgTypeFloat()))
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_FLOAT")));
|
|
else if (tmp->equivalentToType(C_Type(SgTypeDouble())) || tmp->equivalentToType(SgTypeDouble()))
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_DOUBLE")));
|
|
else if (tmp->equivalentToType(indexTypeInKernel(rt_INT)))
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_INT")));
|
|
else if (tmp->equivalentToType(indexTypeInKernel(rt_LONG)))
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LONG")));
|
|
else if (tmp->equivalentToType(indexTypeInKernel(rt_LLONG)))
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_LLONG")));
|
|
else if (tmp->equivalentToType(C_Derived_Type(s_cmplx)))
|
|
{
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_FLOAT_COMPLEX")));
|
|
|
|
SgSymbol *symb = createNewFunctionSymbol("real");
|
|
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
|
|
|
|
symb = createNewFunctionSymbol("imag");
|
|
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
|
|
dontCast = true;
|
|
}
|
|
else if (tmp->equivalentToType(C_Derived_Type(s_dcmplx)))
|
|
{
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_DOUBLE_COMPLEX")));
|
|
|
|
SgSymbol *symb = createNewFunctionSymbol("real");
|
|
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
|
|
|
|
symb = createNewFunctionSymbol("imag");
|
|
RTC_FCall[fc]->addArg(*new SgFunctionCallExp(*symb, *new SgExpression(EXPR_LIST, argList->lhs(), NULL, NULL)));
|
|
dontCast = true;
|
|
}
|
|
else
|
|
{
|
|
RTC_FCall[fc]->addArg(*new SgVarRefExp(new SgSymbol(VARIABLE_NAME, "rt_UNKNOWN")));
|
|
fprintf(stderr, "Warning[-rtc]: unknown type with variant %d for kernel lauch\n", tmp->variant());
|
|
}
|
|
|
|
if (dontCast == false)
|
|
RTC_FCall[fc]->addArg(*new SgCastExp(*tmp, *argList->lhs()));
|
|
}
|
|
|
|
argList = argList->rhs();
|
|
}
|
|
}
|
|
|
|
RTC_FKernelArgs.clear();
|
|
RTC_FArgs.clear();
|
|
RTC_FCall.clear();
|
|
}
|
|
|
|
// convert unparse buffer for RTC call
|
|
char* _RTC_convertUnparse(const char* inBuf)
|
|
{
|
|
int count = 0;
|
|
for (unsigned i = 0; i < strlen(inBuf); ++i)
|
|
{
|
|
if (SpecialSymbols.find(inBuf[i]) != SpecialSymbols.end())
|
|
count += strlen(SpecialSymbols[inBuf[i]]);
|
|
}
|
|
|
|
std::string strBuf = "";
|
|
|
|
for (unsigned i = 0; i < strlen(inBuf); ++i)
|
|
{
|
|
if (SpecialSymbols.find(inBuf[i]) != SpecialSymbols.end())
|
|
{
|
|
const char *tmp = SpecialSymbols[inBuf[i]];
|
|
for (unsigned k1 = 0; k1 < strlen(tmp); ++k1)
|
|
strBuf.push_back(tmp[k1]);
|
|
}
|
|
else
|
|
strBuf.push_back(inBuf[i]);
|
|
}
|
|
|
|
strBuf += "#undef dcmplx2\\n\"\n\"#undef cmplx2\\n";
|
|
char *newBuf = new char[strlen(strBuf.c_str()) + 1];
|
|
strcpy(newBuf, strBuf.c_str());
|
|
|
|
return newBuf;
|
|
}
|
|
|
|
// convert cuda kernel to static const char*
|
|
void ACC_RTC_ConvertCudaKernel(SgStatement *cuda_kernel, const char *kernelName)
|
|
{
|
|
if (cuda_kernel != NULL)
|
|
{
|
|
cuda_kernel->addComment("#define dcmplx2 Complex<double>\n#define cmplx2 Complex<float>\nextern \"C\"\n");
|
|
char *buf = copyOfUnparse(UnparseBif_Char(cuda_kernel->thebif, C_LANG));
|
|
char *newBuf = _RTC_convertUnparse(buf);
|
|
|
|
SgPointerType *arrType = new SgPointerType(*C_Type(SgTypeChar()));
|
|
|
|
SgSymbol *cuda_kernel_code = new SgSymbol(VARIABLE_NAME, kernelName, arrType, mod_gpu);
|
|
SgStatement *decl = makeSymbolDeclarationWithInit(cuda_kernel_code, new SgValueExp(newBuf));
|
|
|
|
decl->addDeclSpec(BIT_CONST);
|
|
decl->addDeclSpec(BIT_STATIC);
|
|
cuda_kernel->insertStmtBefore(*decl);
|
|
if(acc_call_list)
|
|
{
|
|
symb_list **call_list = new (symb_list *);
|
|
*call_list = acc_call_list;
|
|
decl->addAttribute(RTC_CALLS, (void*)call_list, sizeof(symb_list *));
|
|
}
|
|
cuda_kernel->deleteStmt();
|
|
delete[] buf;
|
|
}
|
|
}
|
|
|
|
static symb_list *_RTC_addCalledToList(symb_list *call_list, graph_node *gnode)
|
|
{
|
|
edge *gedge;
|
|
|
|
for (gedge = gnode->to_called; gedge; gedge = gedge->next)
|
|
if(gedge->to->st_header)
|
|
{ call_list = AddNewToSymbList(call_list, gedge->to->symb);
|
|
call_list = _RTC_addCalledToList(call_list, gedge->to);
|
|
}
|
|
|
|
return call_list;
|
|
}
|
|
|
|
symb_list *ACC_RTC_ExpandCallList(symb_list *call_list)
|
|
{
|
|
symb_list *sl;
|
|
for (sl = call_list; sl; sl = sl->next)
|
|
{
|
|
if (!ATTR_NODE(sl->symb))
|
|
continue;
|
|
call_list = _RTC_addCalledToList(call_list, GRAPHNODE(sl->symb));
|
|
}
|
|
return call_list;
|
|
}
|
|
|
|
char* _RTC_PrototypesForKernel(symb_list *call_list)
|
|
{
|
|
SgStatement *st = NULL;
|
|
symb_list *sl = call_list;
|
|
st = FunctionPrototype(GRAPHNODE(sl->symb)->st_copy->symbol());
|
|
st->addDeclSpec(BIT_CUDA_DEVICE);
|
|
st->addDeclSpec(BIT_STATIC);
|
|
st->addComment("#define dcmplx2 Complex<double>\n#define cmplx2 Complex<float>\n");
|
|
char *buffer = copyOfUnparse(UnparseBif_Char(st->thebif, C_LANG));
|
|
for (sl = call_list->next; sl; sl = sl->next)
|
|
{
|
|
st = FunctionPrototype(GRAPHNODE(sl->symb)->st_copy->symbol());
|
|
st->addDeclSpec(BIT_CUDA_DEVICE);
|
|
st->addDeclSpec(BIT_STATIC);
|
|
|
|
char *unp_buf = UnparseBif_Char(st->thebif, C_LANG);
|
|
char *buf = new char[strlen(buffer) + strlen(unp_buf) + 1];
|
|
strcpy(buf, buffer);
|
|
strcat(buf, unp_buf);
|
|
delete[] buffer;
|
|
buffer = buf;
|
|
}
|
|
return (buffer);
|
|
}
|
|
|
|
void _RTC_UnparsedFunctionsToKernelConst(SgStatement *stmt)
|
|
{
|
|
if (CALLED_FUNCTIONS(stmt) == NULL)
|
|
return;
|
|
|
|
symb_list *call_list = *CALLED_FUNCTIONS(stmt);
|
|
|
|
graph_node * gnode = NULL;
|
|
char *buffer = _RTC_PrototypesForKernel(call_list);
|
|
|
|
for (; call_list; call_list = call_list->next)
|
|
{ SgStatement *stmt, *end_st;
|
|
gnode = GRAPHNODE(call_list->symb);
|
|
end_st = gnode->st_copy_first->lastNodeOfStmt()->lexNext();
|
|
stmt = gnode->st_copy;
|
|
while (stmt != end_st) //st_copy,...,st_copy_first
|
|
{
|
|
char *unp_buf = UnparseBif_Char(stmt->thebif, C_LANG);
|
|
char *buf = new char[strlen(unp_buf) + strlen(buffer) + 1];
|
|
//buf[0] = '\0';
|
|
strcpy(buf, buffer);
|
|
strcat(buf, unp_buf);
|
|
delete[] buffer;
|
|
buffer = buf;
|
|
stmt = stmt->lastNodeOfStmt()->lexNext();
|
|
}
|
|
}
|
|
buffer = _RTC_convertUnparse(buffer);
|
|
|
|
char *kernel_buf = ((SgValueExp *)((SgVarDeclStmt *)stmt)->initialValue(0))->stringValue();
|
|
char *allBuf = new char[strlen(kernel_buf) + strlen(buffer) + 1];
|
|
strcpy(allBuf, buffer);
|
|
strcat(allBuf, kernel_buf);
|
|
((SgVarDeclStmt *)stmt)->setInitialValue(0, *new SgValueExp(allBuf));
|
|
delete[] kernel_buf;
|
|
delete[] buffer;
|
|
}
|
|
|
|
|
|
void ACC_RTC_AddFunctionsToKernelConsts(SgStatement *first_kernel_const)
|
|
{
|
|
SgStatement *stmt = mod_gpu, *next = NULL;
|
|
|
|
for (stmt = first_kernel_const; stmt; stmt = stmt->lexNext())
|
|
_RTC_UnparsedFunctionsToKernelConst(stmt);
|
|
stmt = mod_gpu;
|
|
next = mod_gpu->lexNext();
|
|
|
|
// extracting function copies
|
|
//while(next->variant() != VAR_DECL)
|
|
|
|
while (next != first_kernel_const)
|
|
{
|
|
stmt = next;
|
|
next = next->lastNodeOfStmt()->lexNext();
|
|
stmt->extractStmt();
|
|
}
|
|
|
|
}
|