Compare commits
30 Commits
concept-ch
...
copy_ast
| Author | SHA1 | Date | |
|---|---|---|---|
| 5e6f06cf59 | |||
| bfe723e1b7 | |||
| f65b3e6300 | |||
| 2e28640860 | |||
| d020107d91 | |||
| ab29965d75 | |||
| 64e1e2b008 | |||
| 6a91c5d5ac | |||
| 192b99f21d | |||
| 871af918ad | |||
| 7bb1741b9a | |||
| aeb4c0b6f9 | |||
| 9c0f9be022 | |||
| a5306eddc1 | |||
| 0f17514eb0 | |||
| 8a1aeed55c | |||
| 05c9f63527 | |||
| c86c5097d7 | |||
| 46ed9bdb3c | |||
| 93c563e073 | |||
| b3b02df569 | |||
| 0887760de1 | |||
| 148c333943 | |||
| 98e5809d24 | |||
| 87b6ed7f4c | |||
| 259f092143 | |||
| 108c9c6fb5 | |||
| 128b40ce3c | |||
| 717aec388b | |||
| f2287d2cd7 |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*~
|
*~
|
||||||
|
tags
|
||||||
depend
|
depend
|
||||||
ispc
|
ispc
|
||||||
ispc_test
|
ispc_test
|
||||||
@@ -12,6 +13,7 @@ tests*/*cpp
|
|||||||
tests*/*run
|
tests*/*run
|
||||||
tests*/*.o
|
tests*/*.o
|
||||||
tests_ispcpp/*.h
|
tests_ispcpp/*.h
|
||||||
|
tests_ispcpp/*.out
|
||||||
tests_ispcpp/*pre*
|
tests_ispcpp/*pre*
|
||||||
logs/
|
logs/
|
||||||
notify_log.log
|
notify_log.log
|
||||||
@@ -23,5 +25,8 @@ examples/*/ref
|
|||||||
examples/*/test
|
examples/*/test
|
||||||
*.swp
|
*.swp
|
||||||
check_isa.exe
|
check_isa.exe
|
||||||
|
.vscode
|
||||||
|
configure
|
||||||
|
ispc.dSYM
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
158
ast.cpp
158
ast.cpp
@@ -42,8 +42,11 @@
|
|||||||
#include "func.h"
|
#include "func.h"
|
||||||
#include "stmt.h"
|
#include "stmt.h"
|
||||||
#include "sym.h"
|
#include "sym.h"
|
||||||
|
#include "type.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ASTNode
|
// ASTNode
|
||||||
|
|
||||||
@@ -55,10 +58,21 @@ ASTNode::~ASTNode() {
|
|||||||
// AST
|
// AST
|
||||||
|
|
||||||
void
|
void
|
||||||
AST::AddFunction(Symbol *sym, Stmt *code) {
|
AST::AddFunction(Symbol *sym, Stmt *code, SymbolTable *symbolTable) {
|
||||||
if (sym == NULL)
|
if (sym == NULL)
|
||||||
return;
|
return;
|
||||||
functions.push_back(new Function(sym, code));
|
|
||||||
|
Function *f = new Function(sym, code);
|
||||||
|
|
||||||
|
if (f->IsPolyFunction()) {
|
||||||
|
std::vector<Function *> *expanded = f->ExpandPolyArguments(symbolTable);
|
||||||
|
for (size_t i=0; i<expanded->size(); i++) {
|
||||||
|
functions.push_back((*expanded)[i]);
|
||||||
|
}
|
||||||
|
delete expanded;
|
||||||
|
} else {
|
||||||
|
functions.push_back(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,7 +86,7 @@ AST::GenerateIR() {
|
|||||||
|
|
||||||
ASTNode *
|
ASTNode *
|
||||||
WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
||||||
void *data) {
|
void *data, ASTPostCallBackFunc preUpdate) {
|
||||||
if (node == NULL)
|
if (node == NULL)
|
||||||
return node;
|
return node;
|
||||||
|
|
||||||
@@ -83,6 +97,10 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (preUpdate != NULL) {
|
||||||
|
node = preUpdate(node, data);
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////
|
||||||
// Handle Statements
|
// Handle Statements
|
||||||
if (llvm::dyn_cast<Stmt>(node) != NULL) {
|
if (llvm::dyn_cast<Stmt>(node) != NULL) {
|
||||||
@@ -106,54 +124,54 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
|||||||
UnmaskedStmt *ums;
|
UnmaskedStmt *ums;
|
||||||
|
|
||||||
if ((es = llvm::dyn_cast<ExprStmt>(node)) != NULL)
|
if ((es = llvm::dyn_cast<ExprStmt>(node)) != NULL)
|
||||||
es->expr = (Expr *)WalkAST(es->expr, preFunc, postFunc, data);
|
es->expr = (Expr *)WalkAST(es->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((ds = llvm::dyn_cast<DeclStmt>(node)) != NULL) {
|
else if ((ds = llvm::dyn_cast<DeclStmt>(node)) != NULL) {
|
||||||
for (unsigned int i = 0; i < ds->vars.size(); ++i)
|
for (unsigned int i = 0; i < ds->vars.size(); ++i)
|
||||||
ds->vars[i].init = (Expr *)WalkAST(ds->vars[i].init, preFunc,
|
ds->vars[i].init = (Expr *)WalkAST(ds->vars[i].init, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((is = llvm::dyn_cast<IfStmt>(node)) != NULL) {
|
else if ((is = llvm::dyn_cast<IfStmt>(node)) != NULL) {
|
||||||
is->test = (Expr *)WalkAST(is->test, preFunc, postFunc, data);
|
is->test = (Expr *)WalkAST(is->test, preFunc, postFunc, data, preUpdate);
|
||||||
is->trueStmts = (Stmt *)WalkAST(is->trueStmts, preFunc,
|
is->trueStmts = (Stmt *)WalkAST(is->trueStmts, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
is->falseStmts = (Stmt *)WalkAST(is->falseStmts, preFunc,
|
is->falseStmts = (Stmt *)WalkAST(is->falseStmts, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((dos = llvm::dyn_cast<DoStmt>(node)) != NULL) {
|
else if ((dos = llvm::dyn_cast<DoStmt>(node)) != NULL) {
|
||||||
dos->testExpr = (Expr *)WalkAST(dos->testExpr, preFunc,
|
dos->testExpr = (Expr *)WalkAST(dos->testExpr, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
dos->bodyStmts = (Stmt *)WalkAST(dos->bodyStmts, preFunc,
|
dos->bodyStmts = (Stmt *)WalkAST(dos->bodyStmts, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((fs = llvm::dyn_cast<ForStmt>(node)) != NULL) {
|
else if ((fs = llvm::dyn_cast<ForStmt>(node)) != NULL) {
|
||||||
fs->init = (Stmt *)WalkAST(fs->init, preFunc, postFunc, data);
|
fs->init = (Stmt *)WalkAST(fs->init, preFunc, postFunc, data, preUpdate);
|
||||||
fs->test = (Expr *)WalkAST(fs->test, preFunc, postFunc, data);
|
fs->test = (Expr *)WalkAST(fs->test, preFunc, postFunc, data, preUpdate);
|
||||||
fs->step = (Stmt *)WalkAST(fs->step, preFunc, postFunc, data);
|
fs->step = (Stmt *)WalkAST(fs->step, preFunc, postFunc, data, preUpdate);
|
||||||
fs->stmts = (Stmt *)WalkAST(fs->stmts, preFunc, postFunc, data);
|
fs->stmts = (Stmt *)WalkAST(fs->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((fes = llvm::dyn_cast<ForeachStmt>(node)) != NULL) {
|
else if ((fes = llvm::dyn_cast<ForeachStmt>(node)) != NULL) {
|
||||||
for (unsigned int i = 0; i < fes->startExprs.size(); ++i)
|
for (unsigned int i = 0; i < fes->startExprs.size(); ++i)
|
||||||
fes->startExprs[i] = (Expr *)WalkAST(fes->startExprs[i], preFunc,
|
fes->startExprs[i] = (Expr *)WalkAST(fes->startExprs[i], preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
for (unsigned int i = 0; i < fes->endExprs.size(); ++i)
|
for (unsigned int i = 0; i < fes->endExprs.size(); ++i)
|
||||||
fes->endExprs[i] = (Expr *)WalkAST(fes->endExprs[i], preFunc,
|
fes->endExprs[i] = (Expr *)WalkAST(fes->endExprs[i], preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
fes->stmts = (Stmt *)WalkAST(fes->stmts, preFunc, postFunc, data);
|
fes->stmts = (Stmt *)WalkAST(fes->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((fas = llvm::dyn_cast<ForeachActiveStmt>(node)) != NULL) {
|
else if ((fas = llvm::dyn_cast<ForeachActiveStmt>(node)) != NULL) {
|
||||||
fas->stmts = (Stmt *)WalkAST(fas->stmts, preFunc, postFunc, data);
|
fas->stmts = (Stmt *)WalkAST(fas->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((fus = llvm::dyn_cast<ForeachUniqueStmt>(node)) != NULL) {
|
else if ((fus = llvm::dyn_cast<ForeachUniqueStmt>(node)) != NULL) {
|
||||||
fus->expr = (Expr *)WalkAST(fus->expr, preFunc, postFunc, data);
|
fus->expr = (Expr *)WalkAST(fus->expr, preFunc, postFunc, data, preUpdate);
|
||||||
fus->stmts = (Stmt *)WalkAST(fus->stmts, preFunc, postFunc, data);
|
fus->stmts = (Stmt *)WalkAST(fus->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((cs = llvm::dyn_cast<CaseStmt>(node)) != NULL)
|
else if ((cs = llvm::dyn_cast<CaseStmt>(node)) != NULL)
|
||||||
cs->stmts = (Stmt *)WalkAST(cs->stmts, preFunc, postFunc, data);
|
cs->stmts = (Stmt *)WalkAST(cs->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((defs = llvm::dyn_cast<DefaultStmt>(node)) != NULL)
|
else if ((defs = llvm::dyn_cast<DefaultStmt>(node)) != NULL)
|
||||||
defs->stmts = (Stmt *)WalkAST(defs->stmts, preFunc, postFunc, data);
|
defs->stmts = (Stmt *)WalkAST(defs->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((ss = llvm::dyn_cast<SwitchStmt>(node)) != NULL) {
|
else if ((ss = llvm::dyn_cast<SwitchStmt>(node)) != NULL) {
|
||||||
ss->expr = (Expr *)WalkAST(ss->expr, preFunc, postFunc, data);
|
ss->expr = (Expr *)WalkAST(ss->expr, preFunc, postFunc, data, preUpdate);
|
||||||
ss->stmts = (Stmt *)WalkAST(ss->stmts, preFunc, postFunc, data);
|
ss->stmts = (Stmt *)WalkAST(ss->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if (llvm::dyn_cast<BreakStmt>(node) != NULL ||
|
else if (llvm::dyn_cast<BreakStmt>(node) != NULL ||
|
||||||
llvm::dyn_cast<ContinueStmt>(node) != NULL ||
|
llvm::dyn_cast<ContinueStmt>(node) != NULL ||
|
||||||
@@ -161,22 +179,22 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
|||||||
// nothing
|
// nothing
|
||||||
}
|
}
|
||||||
else if ((ls = llvm::dyn_cast<LabeledStmt>(node)) != NULL)
|
else if ((ls = llvm::dyn_cast<LabeledStmt>(node)) != NULL)
|
||||||
ls->stmt = (Stmt *)WalkAST(ls->stmt, preFunc, postFunc, data);
|
ls->stmt = (Stmt *)WalkAST(ls->stmt, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((rs = llvm::dyn_cast<ReturnStmt>(node)) != NULL)
|
else if ((rs = llvm::dyn_cast<ReturnStmt>(node)) != NULL)
|
||||||
rs->expr = (Expr *)WalkAST(rs->expr, preFunc, postFunc, data);
|
rs->expr = (Expr *)WalkAST(rs->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((sl = llvm::dyn_cast<StmtList>(node)) != NULL) {
|
else if ((sl = llvm::dyn_cast<StmtList>(node)) != NULL) {
|
||||||
std::vector<Stmt *> &sls = sl->stmts;
|
std::vector<Stmt *> &sls = sl->stmts;
|
||||||
for (unsigned int i = 0; i < sls.size(); ++i)
|
for (unsigned int i = 0; i < sls.size(); ++i)
|
||||||
sls[i] = (Stmt *)WalkAST(sls[i], preFunc, postFunc, data);
|
sls[i] = (Stmt *)WalkAST(sls[i], preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((ps = llvm::dyn_cast<PrintStmt>(node)) != NULL)
|
else if ((ps = llvm::dyn_cast<PrintStmt>(node)) != NULL)
|
||||||
ps->values = (Expr *)WalkAST(ps->values, preFunc, postFunc, data);
|
ps->values = (Expr *)WalkAST(ps->values, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((as = llvm::dyn_cast<AssertStmt>(node)) != NULL)
|
else if ((as = llvm::dyn_cast<AssertStmt>(node)) != NULL)
|
||||||
as->expr = (Expr *)WalkAST(as->expr, preFunc, postFunc, data);
|
as->expr = (Expr *)WalkAST(as->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((dels = llvm::dyn_cast<DeleteStmt>(node)) != NULL)
|
else if ((dels = llvm::dyn_cast<DeleteStmt>(node)) != NULL)
|
||||||
dels->expr = (Expr *)WalkAST(dels->expr, preFunc, postFunc, data);
|
dels->expr = (Expr *)WalkAST(dels->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((ums = llvm::dyn_cast<UnmaskedStmt>(node)) != NULL)
|
else if ((ums = llvm::dyn_cast<UnmaskedStmt>(node)) != NULL)
|
||||||
ums->stmts = (Stmt *)WalkAST(ums->stmts, preFunc, postFunc, data);
|
ums->stmts = (Stmt *)WalkAST(ums->stmts, preFunc, postFunc, data, preUpdate);
|
||||||
else
|
else
|
||||||
FATAL("Unhandled statement type in WalkAST()");
|
FATAL("Unhandled statement type in WalkAST()");
|
||||||
}
|
}
|
||||||
@@ -201,57 +219,57 @@ WalkAST(ASTNode *node, ASTPreCallBackFunc preFunc, ASTPostCallBackFunc postFunc,
|
|||||||
NewExpr *newe;
|
NewExpr *newe;
|
||||||
|
|
||||||
if ((ue = llvm::dyn_cast<UnaryExpr>(node)) != NULL)
|
if ((ue = llvm::dyn_cast<UnaryExpr>(node)) != NULL)
|
||||||
ue->expr = (Expr *)WalkAST(ue->expr, preFunc, postFunc, data);
|
ue->expr = (Expr *)WalkAST(ue->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((be = llvm::dyn_cast<BinaryExpr>(node)) != NULL) {
|
else if ((be = llvm::dyn_cast<BinaryExpr>(node)) != NULL) {
|
||||||
be->arg0 = (Expr *)WalkAST(be->arg0, preFunc, postFunc, data);
|
be->arg0 = (Expr *)WalkAST(be->arg0, preFunc, postFunc, data, preUpdate);
|
||||||
be->arg1 = (Expr *)WalkAST(be->arg1, preFunc, postFunc, data);
|
be->arg1 = (Expr *)WalkAST(be->arg1, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((ae = llvm::dyn_cast<AssignExpr>(node)) != NULL) {
|
else if ((ae = llvm::dyn_cast<AssignExpr>(node)) != NULL) {
|
||||||
ae->lvalue = (Expr *)WalkAST(ae->lvalue, preFunc, postFunc, data);
|
ae->lvalue = (Expr *)WalkAST(ae->lvalue, preFunc, postFunc, data, preUpdate);
|
||||||
ae->rvalue = (Expr *)WalkAST(ae->rvalue, preFunc, postFunc, data);
|
ae->rvalue = (Expr *)WalkAST(ae->rvalue, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((se = llvm::dyn_cast<SelectExpr>(node)) != NULL) {
|
else if ((se = llvm::dyn_cast<SelectExpr>(node)) != NULL) {
|
||||||
se->test = (Expr *)WalkAST(se->test, preFunc, postFunc, data);
|
se->test = (Expr *)WalkAST(se->test, preFunc, postFunc, data, preUpdate);
|
||||||
se->expr1 = (Expr *)WalkAST(se->expr1, preFunc, postFunc, data);
|
se->expr1 = (Expr *)WalkAST(se->expr1, preFunc, postFunc, data, preUpdate);
|
||||||
se->expr2 = (Expr *)WalkAST(se->expr2, preFunc, postFunc, data);
|
se->expr2 = (Expr *)WalkAST(se->expr2, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((el = llvm::dyn_cast<ExprList>(node)) != NULL) {
|
else if ((el = llvm::dyn_cast<ExprList>(node)) != NULL) {
|
||||||
for (unsigned int i = 0; i < el->exprs.size(); ++i)
|
for (unsigned int i = 0; i < el->exprs.size(); ++i)
|
||||||
el->exprs[i] = (Expr *)WalkAST(el->exprs[i], preFunc,
|
el->exprs[i] = (Expr *)WalkAST(el->exprs[i], preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((fce = llvm::dyn_cast<FunctionCallExpr>(node)) != NULL) {
|
else if ((fce = llvm::dyn_cast<FunctionCallExpr>(node)) != NULL) {
|
||||||
fce->func = (Expr *)WalkAST(fce->func, preFunc, postFunc, data);
|
fce->func = (Expr *)WalkAST(fce->func, preFunc, postFunc, data, preUpdate);
|
||||||
fce->args = (ExprList *)WalkAST(fce->args, preFunc, postFunc, data);
|
fce->args = (ExprList *)WalkAST(fce->args, preFunc, postFunc, data, preUpdate);
|
||||||
for (int k = 0; k < 3; k++)
|
for (int k = 0; k < 3; k++)
|
||||||
fce->launchCountExpr[0] = (Expr *)WalkAST(fce->launchCountExpr[0], preFunc,
|
fce->launchCountExpr[0] = (Expr *)WalkAST(fce->launchCountExpr[0], preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((ie = llvm::dyn_cast<IndexExpr>(node)) != NULL) {
|
else if ((ie = llvm::dyn_cast<IndexExpr>(node)) != NULL) {
|
||||||
ie->baseExpr = (Expr *)WalkAST(ie->baseExpr, preFunc, postFunc, data);
|
ie->baseExpr = (Expr *)WalkAST(ie->baseExpr, preFunc, postFunc, data, preUpdate);
|
||||||
ie->index = (Expr *)WalkAST(ie->index, preFunc, postFunc, data);
|
ie->index = (Expr *)WalkAST(ie->index, preFunc, postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if ((me = llvm::dyn_cast<MemberExpr>(node)) != NULL)
|
else if ((me = llvm::dyn_cast<MemberExpr>(node)) != NULL)
|
||||||
me->expr = (Expr *)WalkAST(me->expr, preFunc, postFunc, data);
|
me->expr = (Expr *)WalkAST(me->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((tce = llvm::dyn_cast<TypeCastExpr>(node)) != NULL)
|
else if ((tce = llvm::dyn_cast<TypeCastExpr>(node)) != NULL)
|
||||||
tce->expr = (Expr *)WalkAST(tce->expr, preFunc, postFunc, data);
|
tce->expr = (Expr *)WalkAST(tce->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((re = llvm::dyn_cast<ReferenceExpr>(node)) != NULL)
|
else if ((re = llvm::dyn_cast<ReferenceExpr>(node)) != NULL)
|
||||||
re->expr = (Expr *)WalkAST(re->expr, preFunc, postFunc, data);
|
re->expr = (Expr *)WalkAST(re->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((ptrderef = llvm::dyn_cast<PtrDerefExpr>(node)) != NULL)
|
else if ((ptrderef = llvm::dyn_cast<PtrDerefExpr>(node)) != NULL)
|
||||||
ptrderef->expr = (Expr *)WalkAST(ptrderef->expr, preFunc, postFunc,
|
ptrderef->expr = (Expr *)WalkAST(ptrderef->expr, preFunc, postFunc,
|
||||||
data);
|
data, preUpdate);
|
||||||
else if ((refderef = llvm::dyn_cast<RefDerefExpr>(node)) != NULL)
|
else if ((refderef = llvm::dyn_cast<RefDerefExpr>(node)) != NULL)
|
||||||
refderef->expr = (Expr *)WalkAST(refderef->expr, preFunc, postFunc,
|
refderef->expr = (Expr *)WalkAST(refderef->expr, preFunc, postFunc,
|
||||||
data);
|
data, preUpdate);
|
||||||
else if ((soe = llvm::dyn_cast<SizeOfExpr>(node)) != NULL)
|
else if ((soe = llvm::dyn_cast<SizeOfExpr>(node)) != NULL)
|
||||||
soe->expr = (Expr *)WalkAST(soe->expr, preFunc, postFunc, data);
|
soe->expr = (Expr *)WalkAST(soe->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((aoe = llvm::dyn_cast<AddressOfExpr>(node)) != NULL)
|
else if ((aoe = llvm::dyn_cast<AddressOfExpr>(node)) != NULL)
|
||||||
aoe->expr = (Expr *)WalkAST(aoe->expr, preFunc, postFunc, data);
|
aoe->expr = (Expr *)WalkAST(aoe->expr, preFunc, postFunc, data, preUpdate);
|
||||||
else if ((newe = llvm::dyn_cast<NewExpr>(node)) != NULL) {
|
else if ((newe = llvm::dyn_cast<NewExpr>(node)) != NULL) {
|
||||||
newe->countExpr = (Expr *)WalkAST(newe->countExpr, preFunc,
|
newe->countExpr = (Expr *)WalkAST(newe->countExpr, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
newe->initExpr = (Expr *)WalkAST(newe->initExpr, preFunc,
|
newe->initExpr = (Expr *)WalkAST(newe->initExpr, preFunc,
|
||||||
postFunc, data);
|
postFunc, data, preUpdate);
|
||||||
}
|
}
|
||||||
else if (llvm::dyn_cast<SymbolExpr>(node) != NULL ||
|
else if (llvm::dyn_cast<SymbolExpr>(node) != NULL ||
|
||||||
llvm::dyn_cast<ConstExpr>(node) != NULL ||
|
llvm::dyn_cast<ConstExpr>(node) != NULL ||
|
||||||
@@ -508,3 +526,35 @@ SafeToRunWithMaskAllOff(ASTNode *root) {
|
|||||||
WalkAST(root, lCheckAllOffSafety, NULL, &safe);
|
WalkAST(root, lCheckAllOffSafety, NULL, &safe);
|
||||||
return safe;
|
return safe;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PolyData {
|
||||||
|
const PolyType *polyType;
|
||||||
|
const Type *replacement;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static ASTNode *
|
||||||
|
lTranslatePolyNode(ASTNode *node, void *d) {
|
||||||
|
struct PolyData *data = (struct PolyData*)d;
|
||||||
|
|
||||||
|
return node->ReplacePolyType(data->polyType, data->replacement);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ASTNode *
|
||||||
|
lCopyNode(ASTNode *node, void *) {
|
||||||
|
return node->Copy();
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTNode *
|
||||||
|
TranslatePoly(ASTNode *root, const PolyType *polyType, const Type *replacement) {
|
||||||
|
struct PolyData data;
|
||||||
|
data.polyType = polyType;
|
||||||
|
data.replacement = replacement;
|
||||||
|
|
||||||
|
return WalkAST(root, NULL, lTranslatePolyNode, &data, lCopyNode);
|
||||||
|
}
|
||||||
|
|
||||||
|
ASTNode *
|
||||||
|
CopyAST(ASTNode *root) {
|
||||||
|
return WalkAST(root, NULL, NULL, NULL, lCopyNode);
|
||||||
|
}
|
||||||
|
|||||||
14
ast.h
14
ast.h
@@ -39,6 +39,7 @@
|
|||||||
#define ISPC_AST_H 1
|
#define ISPC_AST_H 1
|
||||||
|
|
||||||
#include "ispc.h"
|
#include "ispc.h"
|
||||||
|
#include "type.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
/** @brief Abstract base class for nodes in the abstract syntax tree (AST).
|
/** @brief Abstract base class for nodes in the abstract syntax tree (AST).
|
||||||
@@ -67,6 +68,10 @@ public:
|
|||||||
pointer in place of the original ASTNode *. */
|
pointer in place of the original ASTNode *. */
|
||||||
virtual ASTNode *TypeCheck() = 0;
|
virtual ASTNode *TypeCheck() = 0;
|
||||||
|
|
||||||
|
virtual ASTNode *Copy() = 0;
|
||||||
|
|
||||||
|
virtual ASTNode *ReplacePolyType(const PolyType *, const Type *) = 0;
|
||||||
|
|
||||||
/** Estimate the execution cost of the node (not including the cost of
|
/** Estimate the execution cost of the node (not including the cost of
|
||||||
the children. The value returned should be based on the COST_*
|
the children. The value returned should be based on the COST_*
|
||||||
enumerant values defined in ispc.h. */
|
enumerant values defined in ispc.h. */
|
||||||
@@ -145,7 +150,7 @@ class AST {
|
|||||||
public:
|
public:
|
||||||
/** Add the AST for a function described by the given declaration
|
/** Add the AST for a function described by the given declaration
|
||||||
information and source code. */
|
information and source code. */
|
||||||
void AddFunction(Symbol *sym, Stmt *code);
|
void AddFunction(Symbol *sym, Stmt *code, SymbolTable *symbolTable=NULL);
|
||||||
|
|
||||||
/** Generate LLVM IR for all of the functions into the current
|
/** Generate LLVM IR for all of the functions into the current
|
||||||
module. */
|
module. */
|
||||||
@@ -174,7 +179,8 @@ typedef ASTNode * (* ASTPostCallBackFunc)(ASTNode *node, void *data);
|
|||||||
doing so, calls postFunc, at the node. The return value from the
|
doing so, calls postFunc, at the node. The return value from the
|
||||||
postFunc call is ignored. */
|
postFunc call is ignored. */
|
||||||
extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc,
|
extern ASTNode *WalkAST(ASTNode *root, ASTPreCallBackFunc preFunc,
|
||||||
ASTPostCallBackFunc postFunc, void *data);
|
ASTPostCallBackFunc postFunc, void *data,
|
||||||
|
ASTPostCallBackFunc preUpdate = NULL);
|
||||||
|
|
||||||
/** Perform simple optimizations on the AST or portion thereof passed to
|
/** Perform simple optimizations on the AST or portion thereof passed to
|
||||||
this function, returning the resulting AST. */
|
this function, returning the resulting AST. */
|
||||||
@@ -204,6 +210,10 @@ extern Stmt *TypeCheck(Stmt *);
|
|||||||
the given root. */
|
the given root. */
|
||||||
extern int EstimateCost(ASTNode *root);
|
extern int EstimateCost(ASTNode *root);
|
||||||
|
|
||||||
|
extern ASTNode * TranslatePoly(ASTNode *root, const PolyType *polyType, const Type *replacement);
|
||||||
|
|
||||||
|
extern ASTNode * CopyAST(ASTNode *root);
|
||||||
|
|
||||||
/** Returns true if it would be safe to run the given code with an "all
|
/** Returns true if it would be safe to run the given code with an "all
|
||||||
off" mask. */
|
off" mask. */
|
||||||
extern bool SafeToRunWithMaskAllOff(ASTNode *root);
|
extern bool SafeToRunWithMaskAllOff(ASTNode *root);
|
||||||
|
|||||||
5
ctx.cpp
5
ctx.cpp
@@ -1927,6 +1927,11 @@ FunctionEmitContext::BinaryOperator(llvm::Instruction::BinaryOps inst,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v0->getType() != v1->getType()) {
|
||||||
|
v0->dump();
|
||||||
|
printf("\n\n");
|
||||||
|
v1->dump();
|
||||||
|
}
|
||||||
AssertPos(currentPos, v0->getType() == v1->getType());
|
AssertPos(currentPos, v0->getType() == v1->getType());
|
||||||
llvm::Type *type = v0->getType();
|
llvm::Type *type = v0->getType();
|
||||||
int arraySize = lArrayVectorWidth(type);
|
int arraySize = lArrayVectorWidth(type);
|
||||||
|
|||||||
248
expr.cpp
248
expr.cpp
@@ -112,6 +112,85 @@ Expr::GetBaseSymbol() const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
Expr::Copy() {
|
||||||
|
Expr *copy;
|
||||||
|
switch (getValueID()) {
|
||||||
|
case AddressOfExprID:
|
||||||
|
copy = (Expr*)new AddressOfExpr(*(AddressOfExpr*)this);
|
||||||
|
break;
|
||||||
|
case AssignExprID:
|
||||||
|
copy = (Expr*)new AssignExpr(*(AssignExpr*)this);
|
||||||
|
break;
|
||||||
|
case BinaryExprID:
|
||||||
|
copy = (Expr*)new BinaryExpr(*(BinaryExpr*)this);
|
||||||
|
break;
|
||||||
|
case ConstExprID:
|
||||||
|
copy = (Expr*)new ConstExpr(*(ConstExpr*)this);
|
||||||
|
break;
|
||||||
|
case PtrDerefExprID:
|
||||||
|
copy = (Expr*)new PtrDerefExpr(*(PtrDerefExpr*)this);
|
||||||
|
break;
|
||||||
|
case RefDerefExprID:
|
||||||
|
copy = (Expr*)new RefDerefExpr(*(RefDerefExpr*)this);
|
||||||
|
break;
|
||||||
|
case ExprListID:
|
||||||
|
copy = (Expr*)new ExprList(*(ExprList*)this);
|
||||||
|
break;
|
||||||
|
case FunctionCallExprID:
|
||||||
|
copy = (Expr*)new FunctionCallExpr(*(FunctionCallExpr*)this);
|
||||||
|
break;
|
||||||
|
case FunctionSymbolExprID:
|
||||||
|
copy = (Expr*)new FunctionSymbolExpr(*(FunctionSymbolExpr*)this);
|
||||||
|
break;
|
||||||
|
case IndexExprID:
|
||||||
|
copy = (Expr*)new IndexExpr(*(IndexExpr*)this);
|
||||||
|
break;
|
||||||
|
case StructMemberExprID:
|
||||||
|
copy = (Expr*)new StructMemberExpr(*(StructMemberExpr*)this);
|
||||||
|
break;
|
||||||
|
case VectorMemberExprID:
|
||||||
|
copy = (Expr*)new VectorMemberExpr(*(VectorMemberExpr*)this);
|
||||||
|
break;
|
||||||
|
case NewExprID:
|
||||||
|
copy = (Expr*)new NewExpr(*(NewExpr*)this);
|
||||||
|
break;
|
||||||
|
case NullPointerExprID:
|
||||||
|
copy = (Expr*)new NullPointerExpr(*(NullPointerExpr*)this);
|
||||||
|
break;
|
||||||
|
case ReferenceExprID:
|
||||||
|
copy = (Expr*)new ReferenceExpr(*(ReferenceExpr*)this);
|
||||||
|
break;
|
||||||
|
case SelectExprID:
|
||||||
|
copy = (Expr*)new SelectExpr(*(SelectExpr*)this);
|
||||||
|
break;
|
||||||
|
case SizeOfExprID:
|
||||||
|
copy = (Expr*)new SizeOfExpr(*(SizeOfExpr*)this);
|
||||||
|
break;
|
||||||
|
case SymbolExprID:
|
||||||
|
copy = (Expr*)new SymbolExpr(*(SymbolExpr*)this);
|
||||||
|
break;
|
||||||
|
case SyncExprID:
|
||||||
|
copy = (Expr*)new SyncExpr(*(SyncExpr*)this);
|
||||||
|
break;
|
||||||
|
case TypeCastExprID:
|
||||||
|
copy = (Expr*)new TypeCastExpr(*(TypeCastExpr*)this);
|
||||||
|
break;
|
||||||
|
case UnaryExprID:
|
||||||
|
copy = (Expr*)new UnaryExpr(*(UnaryExpr*)this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FATAL("Unmatched case in Expr::Copy");
|
||||||
|
copy = this; // just to silence the compiler
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
Expr::ReplacePolyType(const PolyType *, const Type *) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
/** If a conversion from 'fromAtomicType' to 'toAtomicType' may cause lost
|
/** If a conversion from 'fromAtomicType' to 'toAtomicType' may cause lost
|
||||||
@@ -276,6 +355,8 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
|
|||||||
const AtomicType *fromAtomicType = CastType<AtomicType>(fromType);
|
const AtomicType *fromAtomicType = CastType<AtomicType>(fromType);
|
||||||
const PointerType *fromPointerType = CastType<PointerType>(fromType);
|
const PointerType *fromPointerType = CastType<PointerType>(fromType);
|
||||||
const PointerType *toPointerType = CastType<PointerType>(toType);
|
const PointerType *toPointerType = CastType<PointerType>(toType);
|
||||||
|
const PolyType *fromPolyType = CastType<PolyType>(fromType);
|
||||||
|
const PolyType *toPolyType = CastType<PolyType>(toType);
|
||||||
|
|
||||||
// Do this early, since for the case of a conversion like
|
// Do this early, since for the case of a conversion like
|
||||||
// "float foo[10]" -> "float * uniform foo", we have what's seemingly
|
// "float foo[10]" -> "float * uniform foo", we have what's seemingly
|
||||||
@@ -544,6 +625,21 @@ lDoTypeConv(const Type *fromType, const Type *toType, Expr **expr,
|
|||||||
goto typecast_ok;
|
goto typecast_ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// atomic -> polymorphic
|
||||||
|
if ((fromAtomicType || fromPolyType) && toPolyType) {
|
||||||
|
if (toPolyType->CanBeType(fromType)) {
|
||||||
|
goto typecast_ok;
|
||||||
|
} else {
|
||||||
|
if (!failureOk) {
|
||||||
|
Error(pos, "Can't convert between \"%s\" and polymorphic type "
|
||||||
|
"\"%s\" for %s", fromType->GetString().c_str(),
|
||||||
|
toPolyType->GetString().c_str(), errorMsgBase);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// from here on out, the from type can only be atomic something or
|
// from here on out, the from type can only be atomic something or
|
||||||
// other...
|
// other...
|
||||||
if (fromAtomicType == NULL) {
|
if (fromAtomicType == NULL) {
|
||||||
@@ -4653,6 +4749,23 @@ IndexExpr::TypeCheck() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
IndexExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
if (index == NULL || baseExpr == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(GetType()->GetBaseType(), from)) {
|
||||||
|
type = PolyType::ReplaceType(type, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(GetLValueType()->GetBaseType(), from)) {
|
||||||
|
lvalueType = new PointerType(to, lvalueType->GetVariability(),
|
||||||
|
lvalueType->IsConstType());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
IndexExpr::EstimateCost() const {
|
IndexExpr::EstimateCost() const {
|
||||||
@@ -4718,27 +4831,6 @@ lIdentifierToVectorElement(char id) {
|
|||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// StructMemberExpr
|
// StructMemberExpr
|
||||||
|
|
||||||
class StructMemberExpr : public MemberExpr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
|
||||||
SourcePos idpos, bool derefLValue);
|
|
||||||
|
|
||||||
static inline bool classof(StructMemberExpr const*) { return true; }
|
|
||||||
static inline bool classof(ASTNode const* N) {
|
|
||||||
return N->getValueID() == StructMemberExprID;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Type *GetType() const;
|
|
||||||
const Type *GetLValueType() const;
|
|
||||||
int getElementNumber() const;
|
|
||||||
const Type *getElementType() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const StructType *getStructType() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
StructMemberExpr::StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
StructMemberExpr::StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
SourcePos idpos, bool derefLValue)
|
SourcePos idpos, bool derefLValue)
|
||||||
: MemberExpr(e, id, p, idpos, derefLValue, StructMemberExprID) {
|
: MemberExpr(e, id, p, idpos, derefLValue, StructMemberExprID) {
|
||||||
@@ -4890,31 +4982,6 @@ StructMemberExpr::getStructType() const {
|
|||||||
//////////////////////////////////////////////////
|
//////////////////////////////////////////////////
|
||||||
// VectorMemberExpr
|
// VectorMemberExpr
|
||||||
|
|
||||||
class VectorMemberExpr : public MemberExpr
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
|
||||||
SourcePos idpos, bool derefLValue);
|
|
||||||
|
|
||||||
static inline bool classof(VectorMemberExpr const*) { return true; }
|
|
||||||
static inline bool classof(ASTNode const* N) {
|
|
||||||
return N->getValueID() == VectorMemberExprID;
|
|
||||||
}
|
|
||||||
|
|
||||||
llvm::Value *GetValue(FunctionEmitContext* ctx) const;
|
|
||||||
llvm::Value *GetLValue(FunctionEmitContext* ctx) const;
|
|
||||||
const Type *GetType() const;
|
|
||||||
const Type *GetLValueType() const;
|
|
||||||
|
|
||||||
int getElementNumber() const;
|
|
||||||
const Type *getElementType() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
const VectorType *exprVectorType;
|
|
||||||
const VectorType *memberType;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
VectorMemberExpr::VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
VectorMemberExpr::VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
SourcePos idpos, bool derefLValue)
|
SourcePos idpos, bool derefLValue)
|
||||||
: MemberExpr(e, id, p, idpos, derefLValue, VectorMemberExprID) {
|
: MemberExpr(e, id, p, idpos, derefLValue, VectorMemberExprID) {
|
||||||
@@ -5295,6 +5362,19 @@ MemberExpr::Optimize() {
|
|||||||
return expr ? this : NULL;
|
return expr ? this : NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
MemberExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
if (expr == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(GetType()->GetBaseType(), from)) {
|
||||||
|
type = PolyType::ReplaceType(type, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
MemberExpr::EstimateCost() const {
|
MemberExpr::EstimateCost() const {
|
||||||
@@ -7093,10 +7173,16 @@ TypeCastExpr::GetValue(FunctionEmitContext *ctx) const {
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
return ctx->IntToPtrInst(exprVal, llvmToType, "int_to_ptr");
|
return ctx->IntToPtrInst(exprVal, llvmToType, "int_to_ptr");
|
||||||
}
|
} else if (CastType<PolyType>(toType)) {
|
||||||
else {
|
Error(pos, "Unexpected polymorphic type cast to \"%s\"",
|
||||||
|
toType->GetString().c_str());
|
||||||
|
return NULL;
|
||||||
|
} else {
|
||||||
const AtomicType *toAtomic = CastType<AtomicType>(toType);
|
const AtomicType *toAtomic = CastType<AtomicType>(toType);
|
||||||
// typechecking should ensure this is the case
|
// typechecking should ensure this is the case
|
||||||
|
if (!toAtomic) {
|
||||||
|
fprintf(stderr, "I want %s to be atomic\n", toType->GetString().c_str());
|
||||||
|
}
|
||||||
AssertPos(pos, toAtomic != NULL);
|
AssertPos(pos, toAtomic != NULL);
|
||||||
|
|
||||||
return lTypeConvAtomic(ctx, exprVal, toAtomic, fromAtomic, pos);
|
return lTypeConvAtomic(ctx, exprVal, toAtomic, fromAtomic, pos);
|
||||||
@@ -7326,6 +7412,18 @@ TypeCastExpr::Optimize() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
TypeCastExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
if (type == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(type->GetBaseType(), from)) {
|
||||||
|
type = PolyType::ReplaceType(type, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
TypeCastExpr::EstimateCost() const {
|
TypeCastExpr::EstimateCost() const {
|
||||||
@@ -7996,6 +8094,24 @@ SymbolExpr::Optimize() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
SymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
if (!symbol)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
Symbol *tmp = m->symbolTable->LookupVariable(symbol->name.c_str());
|
||||||
|
if (tmp) {
|
||||||
|
tmp->parentFunction = symbol->parentFunction;
|
||||||
|
symbol = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(symbol->type->GetBaseType(), from)) {
|
||||||
|
symbol->type = PolyType::ReplaceType(symbol->type, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
SymbolExpr::EstimateCost() const {
|
SymbolExpr::EstimateCost() const {
|
||||||
@@ -8065,6 +8181,14 @@ FunctionSymbolExpr::Optimize() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
FunctionSymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
// force re-evaluation of overloaded type
|
||||||
|
this->triedToResolve = false;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
FunctionSymbolExpr::EstimateCost() const {
|
FunctionSymbolExpr::EstimateCost() const {
|
||||||
@@ -8311,6 +8435,16 @@ FunctionSymbolExpr::computeOverloadCost(const FunctionType *ftype,
|
|||||||
cost[i] += 8 * costScale;
|
cost[i] += 8 * costScale;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (callTypeNC->IsPolymorphicType()) {
|
||||||
|
const PolyType *callTypeP =
|
||||||
|
CastType<PolyType>(callTypeNC->GetBaseType());
|
||||||
|
if (callTypeP->CanBeType(fargTypeNC->GetBaseType()) &&
|
||||||
|
callTypeNC->IsArrayType() == fargTypeNC->IsArrayType() &&
|
||||||
|
callTypeNC->IsPointerType() == fargTypeNC->IsPointerType()){
|
||||||
|
cost[i] += 8 * costScale;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fargType->IsVaryingType() && callType->IsUniformType()) {
|
if (fargType->IsVaryingType() && callType->IsUniformType()) {
|
||||||
// Here we deal with brodcasting uniform to varying.
|
// Here we deal with brodcasting uniform to varying.
|
||||||
// callType - varying and fargType - uniform is forbidden.
|
// callType - varying and fargType - uniform is forbidden.
|
||||||
@@ -8437,6 +8571,12 @@ FunctionSymbolExpr::ResolveOverloads(SourcePos argPos,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (matches.size() > 1) {
|
else if (matches.size() > 1) {
|
||||||
|
for (size_t i=0; i<argTypes.size(); i++) {
|
||||||
|
if (argTypes[i]->IsPolymorphicType()) {
|
||||||
|
matchingFunc = matches[0];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Multiple matches: ambiguous
|
// Multiple matches: ambiguous
|
||||||
std::string candidateMessage =
|
std::string candidateMessage =
|
||||||
lGetOverloadCandidateMessage(matches, argTypes, argCouldBeNULL);
|
lGetOverloadCandidateMessage(matches, argTypes, argCouldBeNULL);
|
||||||
@@ -8794,6 +8934,18 @@ NewExpr::Optimize() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr *
|
||||||
|
NewExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
if (!allocType)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (Type::EqualForReplacement(allocType->GetBaseType(), from)) {
|
||||||
|
allocType = PolyType::ReplaceType(allocType, to);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
NewExpr::Print() const {
|
NewExpr::Print() const {
|
||||||
|
|||||||
56
expr.h
56
expr.h
@@ -96,6 +96,11 @@ public:
|
|||||||
encountered, NULL should be returned. */
|
encountered, NULL should be returned. */
|
||||||
virtual Expr *TypeCheck() = 0;
|
virtual Expr *TypeCheck() = 0;
|
||||||
|
|
||||||
|
Expr *Copy();
|
||||||
|
|
||||||
|
/** This method replaces a polymorphic type with a specific atomic type */
|
||||||
|
Expr *ReplacePolyType(const PolyType *polyType, const Type *replacement);
|
||||||
|
|
||||||
/** Prints the expression to standard output (used for debugging). */
|
/** Prints the expression to standard output (used for debugging). */
|
||||||
virtual void Print() const = 0;
|
virtual void Print() const = 0;
|
||||||
};
|
};
|
||||||
@@ -324,6 +329,7 @@ public:
|
|||||||
|
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
|
||||||
Expr *baseExpr, *index;
|
Expr *baseExpr, *index;
|
||||||
@@ -357,6 +363,7 @@ public:
|
|||||||
void Print() const;
|
void Print() const;
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
|
||||||
virtual int getElementNumber() const = 0;
|
virtual int getElementNumber() const = 0;
|
||||||
@@ -379,6 +386,51 @@ protected:
|
|||||||
mutable const Type *type, *lvalueType;
|
mutable const Type *type, *lvalueType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class StructMemberExpr : public MemberExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
StructMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos, bool derefLValue);
|
||||||
|
|
||||||
|
static inline bool classof(StructMemberExpr const*) { return true; }
|
||||||
|
static inline bool classof(ASTNode const* N) {
|
||||||
|
return N->getValueID() == StructMemberExprID;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type *GetType() const;
|
||||||
|
const Type *GetLValueType() const;
|
||||||
|
int getElementNumber() const;
|
||||||
|
const Type *getElementType() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const StructType *getStructType() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class VectorMemberExpr : public MemberExpr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
VectorMemberExpr(Expr *e, const char *id, SourcePos p,
|
||||||
|
SourcePos idpos, bool derefLValue);
|
||||||
|
|
||||||
|
static inline bool classof(VectorMemberExpr const*) { return true; }
|
||||||
|
static inline bool classof(ASTNode const* N) {
|
||||||
|
return N->getValueID() == VectorMemberExprID;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::Value *GetValue(FunctionEmitContext* ctx) const;
|
||||||
|
llvm::Value *GetLValue(FunctionEmitContext* ctx) const;
|
||||||
|
const Type *GetType() const;
|
||||||
|
const Type *GetLValueType() const;
|
||||||
|
|
||||||
|
int getElementNumber() const;
|
||||||
|
const Type *getElementType() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VectorType *exprVectorType;
|
||||||
|
const VectorType *memberType;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** @brief Expression representing a compile-time constant value.
|
/** @brief Expression representing a compile-time constant value.
|
||||||
|
|
||||||
@@ -522,6 +574,7 @@ public:
|
|||||||
void Print() const;
|
void Print() const;
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
Symbol *GetBaseSymbol() const;
|
Symbol *GetBaseSymbol() const;
|
||||||
llvm::Constant *GetConstant(const Type *type) const;
|
llvm::Constant *GetConstant(const Type *type) const;
|
||||||
@@ -681,6 +734,7 @@ public:
|
|||||||
Symbol *GetBaseSymbol() const;
|
Symbol *GetBaseSymbol() const;
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
void Print() const;
|
void Print() const;
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
|
||||||
@@ -707,6 +761,7 @@ public:
|
|||||||
Symbol *GetBaseSymbol() const;
|
Symbol *GetBaseSymbol() const;
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
void Print() const;
|
void Print() const;
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
llvm::Constant *GetConstant(const Type *type) const;
|
llvm::Constant *GetConstant(const Type *type) const;
|
||||||
@@ -809,6 +864,7 @@ public:
|
|||||||
const Type *GetType() const;
|
const Type *GetType() const;
|
||||||
Expr *TypeCheck();
|
Expr *TypeCheck();
|
||||||
Expr *Optimize();
|
Expr *Optimize();
|
||||||
|
Expr *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
void Print() const;
|
void Print() const;
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
|
||||||
|
|||||||
102
func.cpp
102
func.cpp
@@ -45,6 +45,7 @@
|
|||||||
#include "sym.h"
|
#include "sym.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
#if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 // 3.2
|
#if ISPC_LLVM_VERSION == ISPC_LLVM_3_2 // 3.2
|
||||||
#ifdef ISPC_NVPTX_ENABLED
|
#ifdef ISPC_NVPTX_ENABLED
|
||||||
@@ -89,7 +90,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <llvm/Support/ToolOutputFile.h>
|
#include <llvm/Support/ToolOutputFile.h>
|
||||||
|
|
||||||
Function::Function(Symbol *s, Stmt *c) {
|
Function::Function(Symbol *s, Stmt *c, bool typecheck) {
|
||||||
sym = s;
|
sym = s;
|
||||||
code = c;
|
code = c;
|
||||||
|
|
||||||
@@ -97,13 +98,15 @@ Function::Function(Symbol *s, Stmt *c) {
|
|||||||
Assert(maskSymbol != NULL);
|
Assert(maskSymbol != NULL);
|
||||||
|
|
||||||
if (code != NULL) {
|
if (code != NULL) {
|
||||||
code = TypeCheck(code);
|
if (typecheck) {
|
||||||
|
code = TypeCheck(code);
|
||||||
|
|
||||||
if (code != NULL && g->debugPrint) {
|
if (code != NULL && g->debugPrint) {
|
||||||
printf("After typechecking function \"%s\":\n",
|
printf("After typechecking function \"%s\":\n",
|
||||||
sym->name.c_str());
|
sym->name.c_str());
|
||||||
code->Print(0);
|
code->Print(0);
|
||||||
printf("---------------------\n");
|
printf("---------------------\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code != NULL) {
|
if (code != NULL) {
|
||||||
@@ -134,6 +137,7 @@ Function::Function(Symbol *s, Stmt *c) {
|
|||||||
args.push_back(sym);
|
args.push_back(sym);
|
||||||
|
|
||||||
const Type *t = type->GetParameterType(i);
|
const Type *t = type->GetParameterType(i);
|
||||||
|
|
||||||
if (sym != NULL && CastType<ReferenceType>(t) == NULL)
|
if (sym != NULL && CastType<ReferenceType>(t) == NULL)
|
||||||
sym->parentFunction = this;
|
sym->parentFunction = this;
|
||||||
}
|
}
|
||||||
@@ -627,3 +631,87 @@ Function::GenerateIR() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool
|
||||||
|
Function::IsPolyFunction() const {
|
||||||
|
for (size_t i = 0; i < args.size(); i++) {
|
||||||
|
if (args[i]->type->IsPolymorphicType()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Function *> *
|
||||||
|
Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
|
||||||
|
Assert(symbolTable != NULL);
|
||||||
|
|
||||||
|
std::vector<Function *> *expanded = new std::vector<Function *>();
|
||||||
|
|
||||||
|
std::vector<Symbol *> versions = symbolTable->LookupPolyFunction(sym->name.c_str());
|
||||||
|
|
||||||
|
const FunctionType *func = CastType<FunctionType>(sym->type);
|
||||||
|
|
||||||
|
for (size_t i=0; i<versions.size(); i++) {
|
||||||
|
if (g->debugPrint) {
|
||||||
|
printf("%s before replacing anything:\n", sym->name.c_str());
|
||||||
|
code->Print(0);
|
||||||
|
}
|
||||||
|
const FunctionType *ft = CastType<FunctionType>(versions[i]->type);
|
||||||
|
|
||||||
|
symbolTable->PushScope();
|
||||||
|
|
||||||
|
Symbol *s = symbolTable->LookupFunction(versions[i]->name.c_str(), ft);
|
||||||
|
Stmt *ncode = (Stmt*)CopyAST(code);
|
||||||
|
|
||||||
|
Function *f = new Function(s, ncode, false);
|
||||||
|
|
||||||
|
for (size_t j=0; j<args.size(); j++) {
|
||||||
|
f->args[j] = new Symbol(*args[j]);
|
||||||
|
symbolTable->AddVariable(f->args[j], false);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j=0; j<ft->GetNumParameters(); j++) {
|
||||||
|
if (func->GetParameterType(j)->IsPolymorphicType()) {
|
||||||
|
const PolyType *from = CastType<PolyType>(
|
||||||
|
func->GetParameterType(j)->GetBaseType());
|
||||||
|
|
||||||
|
f->code = (Stmt*)TranslatePoly(f->code, from,
|
||||||
|
ft->GetParameterType(j)->GetBaseType());
|
||||||
|
if (g->debugPrint) {
|
||||||
|
printf("%s after replacing %s with %s:\n\n",
|
||||||
|
sym->name.c_str(), from->GetString().c_str(),
|
||||||
|
ft->GetParameterType(j)->GetBaseType()->GetString().c_str());
|
||||||
|
|
||||||
|
f->code->Print(0);
|
||||||
|
|
||||||
|
printf("------------------------------------------\n\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// we didn't typecheck before, now we can
|
||||||
|
f->code = TypeCheck(f->code);
|
||||||
|
|
||||||
|
f->code = Optimize(f->code);
|
||||||
|
|
||||||
|
if (g->debugPrint) {
|
||||||
|
printf("After optimizing expanded function \"%s\":\n",
|
||||||
|
f->sym->name.c_str());
|
||||||
|
f->code->Print(0);
|
||||||
|
printf("---------------------\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
symbolTable->PopScope();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
expanded->push_back(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expanded;
|
||||||
|
}
|
||||||
|
|||||||
8
func.h
8
func.h
@@ -39,11 +39,12 @@
|
|||||||
#define ISPC_FUNC_H 1
|
#define ISPC_FUNC_H 1
|
||||||
|
|
||||||
#include "ispc.h"
|
#include "ispc.h"
|
||||||
|
#include "sym.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Function {
|
class Function {
|
||||||
public:
|
public:
|
||||||
Function(Symbol *sym, Stmt *code);
|
Function(Symbol *sym, Stmt *code, bool typecheck=true);
|
||||||
|
|
||||||
const Type *GetReturnType() const;
|
const Type *GetReturnType() const;
|
||||||
const FunctionType *GetType() const;
|
const FunctionType *GetType() const;
|
||||||
@@ -51,6 +52,11 @@ public:
|
|||||||
/** Generate LLVM IR for the function into the current module. */
|
/** Generate LLVM IR for the function into the current module. */
|
||||||
void GenerateIR();
|
void GenerateIR();
|
||||||
|
|
||||||
|
/** Checks if the function has polymorphic parameters */
|
||||||
|
const bool IsPolyFunction() const;
|
||||||
|
|
||||||
|
std::vector<Function *> *ExpandPolyArguments(SymbolTable *symbolTable) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void emitCode(FunctionEmitContext *ctx, llvm::Function *function,
|
void emitCode(FunctionEmitContext *ctx, llvm::Function *function,
|
||||||
SourcePos firstStmtPos);
|
SourcePos firstStmtPos);
|
||||||
|
|||||||
44
lex.ll
44
lex.ll
@@ -63,31 +63,28 @@ inline int isatty(int) { return 0; }
|
|||||||
#endif // ISPC_IS_WINDOWS
|
#endif // ISPC_IS_WINDOWS
|
||||||
|
|
||||||
static int allTokens[] = {
|
static int allTokens[] = {
|
||||||
TOKEN_ASSERT, TOKEN_BOOL, TOKEN_BREAK, TOKEN_CASE,
|
TOKEN_ASSERT, TOKEN_BOOL, TOKEN_BREAK, TOKEN_CASE, TOKEN_CDO, TOKEN_CFOR,
|
||||||
TOKEN_CDO, TOKEN_CFOR, TOKEN_CIF, TOKEN_CWHILE,
|
TOKEN_CIF, TOKEN_CWHILE, TOKEN_CONST, TOKEN_CONTINUE, TOKEN_DEFAULT, TOKEN_DO,
|
||||||
TOKEN_CONST, TOKEN_CONTINUE, TOKEN_DEFAULT, TOKEN_DO,
|
TOKEN_DELETE, TOKEN_DOUBLE, TOKEN_ELSE, TOKEN_ENUM, TOKEN_EXPORT,
|
||||||
TOKEN_DELETE, TOKEN_DOUBLE, TOKEN_ELSE, TOKEN_ENUM,
|
TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FLOAT, TOKEN_FLOATING, TOKEN_FOR,
|
||||||
TOKEN_EXPORT, TOKEN_EXTERN, TOKEN_FALSE, TOKEN_FLOAT, TOKEN_FOR,
|
|
||||||
TOKEN_FOREACH, TOKEN_FOREACH_ACTIVE, TOKEN_FOREACH_TILED,
|
TOKEN_FOREACH, TOKEN_FOREACH_ACTIVE, TOKEN_FOREACH_TILED,
|
||||||
TOKEN_FOREACH_UNIQUE, TOKEN_GOTO, TOKEN_IF, TOKEN_IN, TOKEN_INLINE,
|
TOKEN_FOREACH_UNIQUE, TOKEN_GOTO, TOKEN_IF, TOKEN_IN, TOKEN_INLINE, TOKEN_INT,
|
||||||
TOKEN_INT, TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_LAUNCH,
|
TOKEN_INT8, TOKEN_INT16, TOKEN_INT, TOKEN_INT64, TOKEN_INTEGER, TOKEN_LAUNCH,
|
||||||
TOKEN_NEW, TOKEN_NULL, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA, TOKEN_SIGNED,
|
TOKEN_NEW, TOKEN_NULL, TOKEN_NUMBER, TOKEN_PRINT, TOKEN_RETURN, TOKEN_SOA,
|
||||||
TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH, TOKEN_SYNC,
|
TOKEN_SIGNED, TOKEN_SIZEOF, TOKEN_STATIC, TOKEN_STRUCT, TOKEN_SWITCH,
|
||||||
TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM, TOKEN_UNMASKED,
|
TOKEN_SYNC, TOKEN_TASK, TOKEN_TRUE, TOKEN_TYPEDEF, TOKEN_UNIFORM,
|
||||||
TOKEN_UNSIGNED, TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE,
|
TOKEN_UNMASKED, TOKEN_UNSIGNED, TOKEN_VARYING, TOKEN_VOID, TOKEN_WHILE,
|
||||||
TOKEN_STRING_C_LITERAL, TOKEN_DOTDOTDOT,
|
TOKEN_STRING_C_LITERAL, TOKEN_DOTDOTDOT, TOKEN_FLOAT_CONSTANT,
|
||||||
TOKEN_FLOAT_CONSTANT, TOKEN_DOUBLE_CONSTANT,
|
TOKEN_DOUBLE_CONSTANT, TOKEN_INT8_CONSTANT, TOKEN_UINT8_CONSTANT,
|
||||||
TOKEN_INT8_CONSTANT, TOKEN_UINT8_CONSTANT,
|
TOKEN_INT16_CONSTANT, TOKEN_UINT16_CONSTANT, TOKEN_INT32_CONSTANT,
|
||||||
TOKEN_INT16_CONSTANT, TOKEN_UINT16_CONSTANT,
|
TOKEN_UINT32_CONSTANT, TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT,
|
||||||
TOKEN_INT32_CONSTANT, TOKEN_UINT32_CONSTANT,
|
|
||||||
TOKEN_INT64_CONSTANT, TOKEN_UINT64_CONSTANT,
|
|
||||||
TOKEN_INC_OP, TOKEN_DEC_OP, TOKEN_LEFT_OP, TOKEN_RIGHT_OP, TOKEN_LE_OP,
|
TOKEN_INC_OP, TOKEN_DEC_OP, TOKEN_LEFT_OP, TOKEN_RIGHT_OP, TOKEN_LE_OP,
|
||||||
TOKEN_GE_OP, TOKEN_EQ_OP, TOKEN_NE_OP, TOKEN_AND_OP, TOKEN_OR_OP,
|
TOKEN_GE_OP, TOKEN_EQ_OP, TOKEN_NE_OP, TOKEN_AND_OP, TOKEN_OR_OP,
|
||||||
TOKEN_MUL_ASSIGN, TOKEN_DIV_ASSIGN, TOKEN_MOD_ASSIGN, TOKEN_ADD_ASSIGN,
|
TOKEN_MUL_ASSIGN, TOKEN_DIV_ASSIGN, TOKEN_MOD_ASSIGN, TOKEN_ADD_ASSIGN,
|
||||||
TOKEN_SUB_ASSIGN, TOKEN_LEFT_ASSIGN, TOKEN_RIGHT_ASSIGN, TOKEN_AND_ASSIGN,
|
TOKEN_SUB_ASSIGN, TOKEN_LEFT_ASSIGN, TOKEN_RIGHT_ASSIGN, TOKEN_AND_ASSIGN,
|
||||||
TOKEN_XOR_ASSIGN, TOKEN_OR_ASSIGN, TOKEN_PTR_OP,
|
TOKEN_XOR_ASSIGN, TOKEN_OR_ASSIGN, TOKEN_PTR_OP,
|
||||||
';', '{', '}', ',', ':', '=', '(', ')', '[', ']', '.', '&', '!', '~', '-',
|
';', '{', '}', ',', ':', '=', '(', ')', '[', ']', '.', '&', '!', '~', '-',
|
||||||
'+', '*', '/', '%', '<', '>', '^', '|', '?',
|
'+', '*', '/', '%', '<', '>', '^', '|', '?', '$'
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<int, std::string> tokenToName;
|
std::map<int, std::string> tokenToName;
|
||||||
@@ -114,6 +111,7 @@ void ParserInit() {
|
|||||||
tokenToName[TOKEN_EXTERN] = "extern";
|
tokenToName[TOKEN_EXTERN] = "extern";
|
||||||
tokenToName[TOKEN_FALSE] = "false";
|
tokenToName[TOKEN_FALSE] = "false";
|
||||||
tokenToName[TOKEN_FLOAT] = "float";
|
tokenToName[TOKEN_FLOAT] = "float";
|
||||||
|
tokenToName[TOKEN_FLOATING] = "floating";
|
||||||
tokenToName[TOKEN_FOR] = "for";
|
tokenToName[TOKEN_FOR] = "for";
|
||||||
tokenToName[TOKEN_FOREACH] = "foreach";
|
tokenToName[TOKEN_FOREACH] = "foreach";
|
||||||
tokenToName[TOKEN_FOREACH_ACTIVE] = "foreach_active";
|
tokenToName[TOKEN_FOREACH_ACTIVE] = "foreach_active";
|
||||||
@@ -127,10 +125,12 @@ void ParserInit() {
|
|||||||
tokenToName[TOKEN_INT8] = "int8";
|
tokenToName[TOKEN_INT8] = "int8";
|
||||||
tokenToName[TOKEN_INT16] = "int16";
|
tokenToName[TOKEN_INT16] = "int16";
|
||||||
tokenToName[TOKEN_INT] = "int";
|
tokenToName[TOKEN_INT] = "int";
|
||||||
|
tokenToName[TOKEN_INTEGER] = "integer";
|
||||||
tokenToName[TOKEN_INT64] = "int64";
|
tokenToName[TOKEN_INT64] = "int64";
|
||||||
tokenToName[TOKEN_LAUNCH] = "launch";
|
tokenToName[TOKEN_LAUNCH] = "launch";
|
||||||
tokenToName[TOKEN_NEW] = "new";
|
tokenToName[TOKEN_NEW] = "new";
|
||||||
tokenToName[TOKEN_NULL] = "NULL";
|
tokenToName[TOKEN_NULL] = "NULL";
|
||||||
|
tokenToName[TOKEN_NUMBER] = "number";
|
||||||
tokenToName[TOKEN_PRINT] = "print";
|
tokenToName[TOKEN_PRINT] = "print";
|
||||||
tokenToName[TOKEN_RETURN] = "return";
|
tokenToName[TOKEN_RETURN] = "return";
|
||||||
tokenToName[TOKEN_SOA] = "soa";
|
tokenToName[TOKEN_SOA] = "soa";
|
||||||
@@ -207,6 +207,7 @@ void ParserInit() {
|
|||||||
tokenToName['|'] = "|";
|
tokenToName['|'] = "|";
|
||||||
tokenToName['?'] = "?";
|
tokenToName['?'] = "?";
|
||||||
tokenToName[';'] = ";";
|
tokenToName[';'] = ";";
|
||||||
|
tokenToName['$'] = "$";
|
||||||
|
|
||||||
tokenNameRemap["TOKEN_ASSERT"] = "\'assert\'";
|
tokenNameRemap["TOKEN_ASSERT"] = "\'assert\'";
|
||||||
tokenNameRemap["TOKEN_BOOL"] = "\'bool\'";
|
tokenNameRemap["TOKEN_BOOL"] = "\'bool\'";
|
||||||
@@ -228,6 +229,7 @@ void ParserInit() {
|
|||||||
tokenNameRemap["TOKEN_EXTERN"] = "\'extern\'";
|
tokenNameRemap["TOKEN_EXTERN"] = "\'extern\'";
|
||||||
tokenNameRemap["TOKEN_FALSE"] = "\'false\'";
|
tokenNameRemap["TOKEN_FALSE"] = "\'false\'";
|
||||||
tokenNameRemap["TOKEN_FLOAT"] = "\'float\'";
|
tokenNameRemap["TOKEN_FLOAT"] = "\'float\'";
|
||||||
|
tokenNameRemap["TOKEN_FLOATING"] = "\'floating\'";
|
||||||
tokenNameRemap["TOKEN_FOR"] = "\'for\'";
|
tokenNameRemap["TOKEN_FOR"] = "\'for\'";
|
||||||
tokenNameRemap["TOKEN_FOREACH"] = "\'foreach\'";
|
tokenNameRemap["TOKEN_FOREACH"] = "\'foreach\'";
|
||||||
tokenNameRemap["TOKEN_FOREACH_ACTIVE"] = "\'foreach_active\'";
|
tokenNameRemap["TOKEN_FOREACH_ACTIVE"] = "\'foreach_active\'";
|
||||||
@@ -243,9 +245,11 @@ void ParserInit() {
|
|||||||
tokenNameRemap["TOKEN_INT16"] = "\'int16\'";
|
tokenNameRemap["TOKEN_INT16"] = "\'int16\'";
|
||||||
tokenNameRemap["TOKEN_INT"] = "\'int\'";
|
tokenNameRemap["TOKEN_INT"] = "\'int\'";
|
||||||
tokenNameRemap["TOKEN_INT64"] = "\'int64\'";
|
tokenNameRemap["TOKEN_INT64"] = "\'int64\'";
|
||||||
|
tokenNameRemap["TOKEN_INTEGER"] = "\'integer\'";
|
||||||
tokenNameRemap["TOKEN_LAUNCH"] = "\'launch\'";
|
tokenNameRemap["TOKEN_LAUNCH"] = "\'launch\'";
|
||||||
tokenNameRemap["TOKEN_NEW"] = "\'new\'";
|
tokenNameRemap["TOKEN_NEW"] = "\'new\'";
|
||||||
tokenNameRemap["TOKEN_NULL"] = "\'NULL\'";
|
tokenNameRemap["TOKEN_NULL"] = "\'NULL\'";
|
||||||
|
tokenNameRemap["TOKEN_NUMBER"] = "\'number\'";
|
||||||
tokenNameRemap["TOKEN_PRINT"] = "\'print\'";
|
tokenNameRemap["TOKEN_PRINT"] = "\'print\'";
|
||||||
tokenNameRemap["TOKEN_RETURN"] = "\'return\'";
|
tokenNameRemap["TOKEN_RETURN"] = "\'return\'";
|
||||||
tokenNameRemap["TOKEN_SOA"] = "\'soa\'";
|
tokenNameRemap["TOKEN_SOA"] = "\'soa\'";
|
||||||
@@ -381,6 +385,7 @@ export { RT; return TOKEN_EXPORT; }
|
|||||||
extern { RT; return TOKEN_EXTERN; }
|
extern { RT; return TOKEN_EXTERN; }
|
||||||
false { RT; return TOKEN_FALSE; }
|
false { RT; return TOKEN_FALSE; }
|
||||||
float { RT; return TOKEN_FLOAT; }
|
float { RT; return TOKEN_FLOAT; }
|
||||||
|
floating { RT; return TOKEN_FLOATING; }
|
||||||
for { RT; return TOKEN_FOR; }
|
for { RT; return TOKEN_FOR; }
|
||||||
foreach { RT; return TOKEN_FOREACH; }
|
foreach { RT; return TOKEN_FOREACH; }
|
||||||
foreach_active { RT; return TOKEN_FOREACH_ACTIVE; }
|
foreach_active { RT; return TOKEN_FOREACH_ACTIVE; }
|
||||||
@@ -395,9 +400,11 @@ int8 { RT; return TOKEN_INT8; }
|
|||||||
int16 { RT; return TOKEN_INT16; }
|
int16 { RT; return TOKEN_INT16; }
|
||||||
int32 { RT; return TOKEN_INT; }
|
int32 { RT; return TOKEN_INT; }
|
||||||
int64 { RT; return TOKEN_INT64; }
|
int64 { RT; return TOKEN_INT64; }
|
||||||
|
integer { RT; return TOKEN_INTEGER; }
|
||||||
launch { RT; return TOKEN_LAUNCH; }
|
launch { RT; return TOKEN_LAUNCH; }
|
||||||
new { RT; return TOKEN_NEW; }
|
new { RT; return TOKEN_NEW; }
|
||||||
NULL { RT; return TOKEN_NULL; }
|
NULL { RT; return TOKEN_NULL; }
|
||||||
|
number { RT; return TOKEN_NUMBER; }
|
||||||
print { RT; return TOKEN_PRINT; }
|
print { RT; return TOKEN_PRINT; }
|
||||||
return { RT; return TOKEN_RETURN; }
|
return { RT; return TOKEN_RETURN; }
|
||||||
soa { RT; return TOKEN_SOA; }
|
soa { RT; return TOKEN_SOA; }
|
||||||
@@ -521,6 +528,7 @@ L?\"(\\.|[^\\"])*\" { lStringConst(&yylval, &yylloc); return TOKEN_STRING_LITERA
|
|||||||
"^" { RT; return '^'; }
|
"^" { RT; return '^'; }
|
||||||
"|" { RT; return '|'; }
|
"|" { RT; return '|'; }
|
||||||
"?" { RT; return '?'; }
|
"?" { RT; return '?'; }
|
||||||
|
"$" { RT; return '$'; }
|
||||||
|
|
||||||
{WHITESPACE} { }
|
{WHITESPACE} { }
|
||||||
|
|
||||||
|
|||||||
138
module.cpp
138
module.cpp
@@ -1009,6 +1009,102 @@ Module::AddFunctionDeclaration(const std::string &name,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Handle Polymorphic functions
|
||||||
|
* a function
|
||||||
|
* int foo(number n, floating, f)
|
||||||
|
* will produce versions such as
|
||||||
|
* int foo(int n, float f)
|
||||||
|
*
|
||||||
|
* these functions will be overloaded if they are not exported, or mangled
|
||||||
|
* if exported */
|
||||||
|
|
||||||
|
std::set<const Type *, bool(*)(const Type*, const Type*)> toExpand(&PolyType::Less);
|
||||||
|
std::vector<const FunctionType *> expanded;
|
||||||
|
expanded.push_back(functionType);
|
||||||
|
|
||||||
|
for (int i=0; i<functionType->GetNumParameters(); i++) {
|
||||||
|
const Type *param = functionType->GetParameterType(i);
|
||||||
|
if (param->IsPolymorphicType() &&
|
||||||
|
!toExpand.count(param->GetBaseType())) {
|
||||||
|
|
||||||
|
toExpand.insert(param->GetBaseType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<const FunctionType *> nextExpanded;
|
||||||
|
for (auto iter = toExpand.begin(); iter != toExpand.end(); iter++) {
|
||||||
|
for (size_t j=0; j<expanded.size(); j++) {
|
||||||
|
const FunctionType *eft = expanded[j];
|
||||||
|
|
||||||
|
const PolyType *pt=CastType<PolyType>(*iter);
|
||||||
|
|
||||||
|
std::vector<AtomicType *>::iterator te;
|
||||||
|
for (te = pt->ExpandBegin(); te != pt->ExpandEnd(); te++) {
|
||||||
|
llvm::SmallVector<const Type *, 8> nargs;
|
||||||
|
llvm::SmallVector<std::string, 8> nargsn;
|
||||||
|
llvm::SmallVector<Expr *, 8> nargsd;
|
||||||
|
llvm::SmallVector<SourcePos, 8> nargsp;
|
||||||
|
for (size_t k=0; k<eft->GetNumParameters(); k++) {
|
||||||
|
if (Type::Equal(eft->GetParameterType(k)->GetBaseType(),
|
||||||
|
pt)) {
|
||||||
|
const Type *r;
|
||||||
|
r = PolyType::ReplaceType(eft->GetParameterType(k),*te);
|
||||||
|
nargs.push_back(r);
|
||||||
|
} else {
|
||||||
|
nargs.push_back(eft->GetParameterType(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
nargsn.push_back(eft->GetParameterName(k));
|
||||||
|
nargsd.push_back(eft->GetParameterDefault(k));
|
||||||
|
nargsp.push_back(eft->GetParameterSourcePos(k));
|
||||||
|
}
|
||||||
|
|
||||||
|
const Type *ret = eft->GetReturnType();
|
||||||
|
if (Type::EqualForReplacement(ret, pt)) {
|
||||||
|
printf("Replaced return type %s\n",
|
||||||
|
ret->GetString().c_str());
|
||||||
|
ret = PolyType::ReplaceType(ret, *te);
|
||||||
|
}
|
||||||
|
|
||||||
|
nextExpanded.push_back(new FunctionType(ret,
|
||||||
|
nargs,
|
||||||
|
nargsn,
|
||||||
|
nargsd,
|
||||||
|
nargsp,
|
||||||
|
eft->isTask,
|
||||||
|
eft->isExported,
|
||||||
|
eft->isExternC,
|
||||||
|
eft->isUnmasked));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
expanded.swap(nextExpanded);
|
||||||
|
nextExpanded.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expanded.size() > 1) {
|
||||||
|
for (size_t i=0; i<expanded.size(); i++) {
|
||||||
|
if (expanded[i]->GetReturnType()->IsPolymorphicType()) {
|
||||||
|
Error(pos, "Unexpected polymorphic return type \"%s\"",
|
||||||
|
expanded[i]->GetReturnType()->GetString().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::string nname = name;
|
||||||
|
if (functionType->isExported || functionType->isExternC) {
|
||||||
|
for (int j=0; j<expanded[i]->GetNumParameters(); j++) {
|
||||||
|
nname += "_";
|
||||||
|
nname += expanded[i]->GetParameterType(j)->Mangle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
symbolTable->MapPolyFunction(name, nname, expanded[i]);
|
||||||
|
AddFunctionDeclaration(nname, expanded[i], storageClass,
|
||||||
|
isInline, pos);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the LLVM FunctionType
|
// Get the LLVM FunctionType
|
||||||
bool disableMask = (storageClass == SC_EXTERN_C);
|
bool disableMask = (storageClass == SC_EXTERN_C);
|
||||||
llvm::FunctionType *llvmFunctionType =
|
llvm::FunctionType *llvmFunctionType =
|
||||||
@@ -1177,14 +1273,7 @@ Module::AddFunctionDefinition(const std::string &name, const FunctionType *type,
|
|||||||
|
|
||||||
sym->pos = code->pos;
|
sym->pos = code->pos;
|
||||||
|
|
||||||
// FIXME: because we encode the parameter names in the function type,
|
ast->AddFunction(sym, code, symbolTable);
|
||||||
// we need to override the function type here in case the function had
|
|
||||||
// earlier been declared with anonymous parameter names but is now
|
|
||||||
// defined with actual names. This is yet another reason we shouldn't
|
|
||||||
// include the names in FunctionType...
|
|
||||||
sym->type = type;
|
|
||||||
|
|
||||||
ast->AddFunction(sym, code);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1899,6 +1988,27 @@ lPrintFunctionDeclarations(FILE *file, const std::vector<Symbol *> &funcs,
|
|||||||
// fprintf(file, "#ifdef __cplusplus\n} /* end extern C */\n#endif // __cplusplus\n");
|
// fprintf(file, "#ifdef __cplusplus\n} /* end extern C */\n#endif // __cplusplus\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lPrintPolyFunctionWrappers(FILE *file, const std::vector<std::string> &funcs) {
|
||||||
|
fprintf(file, "#if defined(__cplusplus)\n");
|
||||||
|
|
||||||
|
for (size_t i=0; i<funcs.size(); i++) {
|
||||||
|
std::vector<Symbol *> poly = m->symbolTable->LookupPolyFunction(funcs[i].c_str());
|
||||||
|
|
||||||
|
for (size_t j=0; j<poly.size(); j++) {
|
||||||
|
const FunctionType *ftype = CastType<FunctionType>(poly[j]->type);
|
||||||
|
Assert(ftype);
|
||||||
|
std::string decl = ftype->GetCDeclaration(funcs[i]);
|
||||||
|
fprintf(file, " %s {\n", decl.c_str());
|
||||||
|
|
||||||
|
std::string call = ftype->GetCCall(poly[j]->name);
|
||||||
|
fprintf(file, " return %s;\n }\n", call.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(file, "#endif // __cplusplus\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -2275,8 +2385,10 @@ Module::writeHeader(const char *fn) {
|
|||||||
// Collect single linear arrays of the exported and extern "C"
|
// Collect single linear arrays of the exported and extern "C"
|
||||||
// functions
|
// functions
|
||||||
std::vector<Symbol *> exportedFuncs, externCFuncs;
|
std::vector<Symbol *> exportedFuncs, externCFuncs;
|
||||||
|
std::vector<std::string> polyFuncs;
|
||||||
m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
|
m->symbolTable->GetMatchingFunctions(lIsExported, &exportedFuncs);
|
||||||
m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
|
m->symbolTable->GetMatchingFunctions(lIsExternC, &externCFuncs);
|
||||||
|
m->symbolTable->GetPolyFunctions(&polyFuncs);
|
||||||
|
|
||||||
// Get all of the struct, vector, and enumerant types used as function
|
// Get all of the struct, vector, and enumerant types used as function
|
||||||
// parameters. These vectors may have repeats.
|
// parameters. These vectors may have repeats.
|
||||||
@@ -2313,6 +2425,16 @@ Module::writeHeader(const char *fn) {
|
|||||||
fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
|
fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
|
||||||
lPrintFunctionDeclarations(f, exportedFuncs);
|
lPrintFunctionDeclarations(f, exportedFuncs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// emit wrappers for polymorphic functions
|
||||||
|
if (polyFuncs.size() > 0) {
|
||||||
|
fprintf(f, "\n");
|
||||||
|
fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
|
||||||
|
fprintf(f, "// Polymorphic function wrappers\n");
|
||||||
|
fprintf(f, "///////////////////////////////////////////////////////////////////////////\n");
|
||||||
|
lPrintPolyFunctionWrappers(f, polyFuncs);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (externCFuncs.size() > 0) {
|
if (externCFuncs.size() > 0) {
|
||||||
fprintf(f, "\n");
|
fprintf(f, "\n");
|
||||||
|
|||||||
41
parse.yy
41
parse.yy
@@ -118,21 +118,20 @@ static void lFinalizeEnumeratorSymbols(std::vector<Symbol *> &enums,
|
|||||||
const EnumType *enumType);
|
const EnumType *enumType);
|
||||||
|
|
||||||
static const char *lBuiltinTokens[] = {
|
static const char *lBuiltinTokens[] = {
|
||||||
"assert", "bool", "break", "case", "cdo",
|
"assert", "bool", "break", "case", "cdo", "cfor", "cif", "cwhile", "const",
|
||||||
"cfor", "cif", "cwhile", "const", "continue", "default",
|
"continue", "default", "do", "delete", "double", "else", "enum", "export",
|
||||||
"do", "delete", "double", "else", "enum", "export", "extern", "false",
|
"extern", "false", "float", "floating", "for", "foreach", "foreach_active",
|
||||||
"float", "for", "foreach", "foreach_active", "foreach_tiled",
|
"foreach_tiled", "foreach_unique", "goto", "if", "in", "inline", "int",
|
||||||
"foreach_unique", "goto", "if", "in", "inline",
|
"int8", "int16", "int32", "int64", "integer", "launch", "new", "NULL",
|
||||||
"int", "int8", "int16", "int32", "int64", "launch", "new", "NULL",
|
"number", "print", "return", "signed", "sizeof", "static", "struct",
|
||||||
"print", "return", "signed", "sizeof", "static", "struct", "switch",
|
"switch", "sync", "task", "true", "typedef", "uniform", "unmasked",
|
||||||
"sync", "task", "true", "typedef", "uniform", "unmasked", "unsigned",
|
"unsigned", "varying", "void", "while", NULL
|
||||||
"varying", "void", "while", NULL
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *lParamListTokens[] = {
|
static const char *lParamListTokens[] = {
|
||||||
"bool", "const", "double", "enum", "false", "float", "int",
|
"bool", "const", "double", "enum", "false", "float", "floating", "int",
|
||||||
"int8", "int16", "int32", "int64", "signed", "struct", "true",
|
"int8", "int16", "int32", "int64", "integer", "number", "signed", "struct",
|
||||||
"uniform", "unsigned", "varying", "void", NULL
|
"true", "uniform", "unsigned", "varying", "void", NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ForeachDimension {
|
struct ForeachDimension {
|
||||||
@@ -159,6 +158,7 @@ struct ForeachDimension {
|
|||||||
const Type *type;
|
const Type *type;
|
||||||
std::vector<std::pair<const Type *, SourcePos> > *typeList;
|
std::vector<std::pair<const Type *, SourcePos> > *typeList;
|
||||||
const AtomicType *atomicType;
|
const AtomicType *atomicType;
|
||||||
|
const PolyType *polyType;
|
||||||
int typeQualifier;
|
int typeQualifier;
|
||||||
StorageClass storageClass;
|
StorageClass storageClass;
|
||||||
Stmt *stmt;
|
Stmt *stmt;
|
||||||
@@ -198,6 +198,7 @@ struct ForeachDimension {
|
|||||||
%token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK TOKEN_DECLSPEC
|
%token TOKEN_EXTERN TOKEN_EXPORT TOKEN_STATIC TOKEN_INLINE TOKEN_TASK TOKEN_DECLSPEC
|
||||||
%token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA TOKEN_UNMASKED
|
%token TOKEN_UNIFORM TOKEN_VARYING TOKEN_TYPEDEF TOKEN_SOA TOKEN_UNMASKED
|
||||||
%token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE
|
%token TOKEN_CHAR TOKEN_INT TOKEN_SIGNED TOKEN_UNSIGNED TOKEN_FLOAT TOKEN_DOUBLE
|
||||||
|
%token TOKEN_INTEGER TOKEN_FLOATING TOKEN_NUMBER
|
||||||
%token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL
|
%token TOKEN_INT8 TOKEN_INT16 TOKEN_INT64 TOKEN_CONST TOKEN_VOID TOKEN_BOOL
|
||||||
%token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE
|
%token TOKEN_ENUM TOKEN_STRUCT TOKEN_TRUE TOKEN_FALSE
|
||||||
|
|
||||||
@@ -244,6 +245,7 @@ struct ForeachDimension {
|
|||||||
%type <type> short_vec_specifier
|
%type <type> short_vec_specifier
|
||||||
%type <typeList> type_specifier_list
|
%type <typeList> type_specifier_list
|
||||||
%type <atomicType> atomic_var_type_specifier
|
%type <atomicType> atomic_var_type_specifier
|
||||||
|
%type <polyType> poly_type_specifier poly_quant_type_specifier
|
||||||
|
|
||||||
%type <typeQualifier> type_qualifier type_qualifier_list
|
%type <typeQualifier> type_qualifier type_qualifier_list
|
||||||
%type <storageClass> storage_class_specifier
|
%type <storageClass> storage_class_specifier
|
||||||
@@ -908,6 +910,7 @@ storage_class_specifier
|
|||||||
|
|
||||||
type_specifier
|
type_specifier
|
||||||
: atomic_var_type_specifier { $$ = $1; }
|
: atomic_var_type_specifier { $$ = $1; }
|
||||||
|
| poly_quant_type_specifier { $$ = $1; }
|
||||||
| TOKEN_TYPE_NAME
|
| TOKEN_TYPE_NAME
|
||||||
{
|
{
|
||||||
const Type *t = m->symbolTable->LookupType(yytext);
|
const Type *t = m->symbolTable->LookupType(yytext);
|
||||||
@@ -950,6 +953,20 @@ atomic_var_type_specifier
|
|||||||
| TOKEN_INT64 { $$ = AtomicType::UniformInt64->GetAsUnboundVariabilityType(); }
|
| TOKEN_INT64 { $$ = AtomicType::UniformInt64->GetAsUnboundVariabilityType(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
poly_type_specifier
|
||||||
|
: TOKEN_FLOATING { $$ = PolyType::UniformFloating->GetAsUnboundVariabilityType(); }
|
||||||
|
| TOKEN_INTEGER { $$ = PolyType::UniformInteger->GetAsUnboundVariabilityType(); }
|
||||||
|
| TOKEN_NUMBER { $$ = PolyType::UniformNumber->GetAsUnboundVariabilityType(); }
|
||||||
|
;
|
||||||
|
|
||||||
|
poly_quant_type_specifier
|
||||||
|
: poly_type_specifier '$' int_constant
|
||||||
|
{
|
||||||
|
$$ = $1->Quantify($3);
|
||||||
|
}
|
||||||
|
| poly_type_specifier { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
short_vec_specifier
|
short_vec_specifier
|
||||||
: atomic_var_type_specifier '<' int_constant '>'
|
: atomic_var_type_specifier '<' int_constant '>'
|
||||||
{
|
{
|
||||||
|
|||||||
116
stmt.cpp
116
stmt.cpp
@@ -35,6 +35,7 @@
|
|||||||
@brief File with definitions classes related to statements in the language
|
@brief File with definitions classes related to statements in the language
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "ast.h"
|
||||||
#include "stmt.h"
|
#include "stmt.h"
|
||||||
#include "ctx.h"
|
#include "ctx.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
@@ -77,6 +78,85 @@ Stmt::Optimize() {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stmt *
|
||||||
|
Stmt::Copy() {
|
||||||
|
Stmt *copy;
|
||||||
|
switch (getValueID()) {
|
||||||
|
case AssertStmtID:
|
||||||
|
copy = (Stmt*)new AssertStmt(*(AssertStmt*)this);
|
||||||
|
break;
|
||||||
|
case BreakStmtID:
|
||||||
|
copy = (Stmt*)new BreakStmt(*(BreakStmt*)this);
|
||||||
|
break;
|
||||||
|
case CaseStmtID:
|
||||||
|
copy = (Stmt*)new CaseStmt(*(CaseStmt*)this);
|
||||||
|
break;
|
||||||
|
case ContinueStmtID:
|
||||||
|
copy = (Stmt*)new ContinueStmt(*(ContinueStmt*)this);
|
||||||
|
break;
|
||||||
|
case DeclStmtID:
|
||||||
|
copy = (Stmt*)new DeclStmt(*(DeclStmt*)this);
|
||||||
|
break;
|
||||||
|
case DefaultStmtID:
|
||||||
|
copy = (Stmt*)new DefaultStmt(*(DefaultStmt*)this);
|
||||||
|
break;
|
||||||
|
case DeleteStmtID:
|
||||||
|
copy = (Stmt*)new DeleteStmt(*(DeleteStmt*)this);
|
||||||
|
break;
|
||||||
|
case DoStmtID:
|
||||||
|
copy = (Stmt*)new DoStmt(*(DoStmt*)this);
|
||||||
|
break;
|
||||||
|
case ExprStmtID:
|
||||||
|
copy = (Stmt*)new ExprStmt(*(ExprStmt*)this);
|
||||||
|
break;
|
||||||
|
case ForeachActiveStmtID:
|
||||||
|
copy = (Stmt*)new ForeachActiveStmt(*(ForeachActiveStmt*)this);
|
||||||
|
break;
|
||||||
|
case ForeachStmtID:
|
||||||
|
copy = (Stmt*)new ForeachStmt(*(ForeachStmt*)this);
|
||||||
|
break;
|
||||||
|
case ForeachUniqueStmtID:
|
||||||
|
copy = (Stmt*)new ForeachUniqueStmt(*(ForeachUniqueStmt*)this);
|
||||||
|
break;
|
||||||
|
case ForStmtID:
|
||||||
|
copy = (Stmt*)new ForStmt(*(ForStmt*)this);
|
||||||
|
break;
|
||||||
|
case GotoStmtID:
|
||||||
|
copy = (Stmt*)new GotoStmt(*(GotoStmt*)this);
|
||||||
|
break;
|
||||||
|
case IfStmtID:
|
||||||
|
copy = (Stmt*)new IfStmt(*(IfStmt*)this);
|
||||||
|
break;
|
||||||
|
case LabeledStmtID:
|
||||||
|
copy = (Stmt*)new LabeledStmt(*(LabeledStmt*)this);
|
||||||
|
break;
|
||||||
|
case PrintStmtID:
|
||||||
|
copy = (Stmt*)new PrintStmt(*(PrintStmt*)this);
|
||||||
|
break;
|
||||||
|
case ReturnStmtID:
|
||||||
|
copy = (Stmt*)new ReturnStmt(*(ReturnStmt*)this);
|
||||||
|
break;
|
||||||
|
case StmtListID:
|
||||||
|
copy = (Stmt*)new StmtList(*(StmtList*)this);
|
||||||
|
break;
|
||||||
|
case SwitchStmtID:
|
||||||
|
copy = (Stmt*)new SwitchStmt(*(SwitchStmt*)this);
|
||||||
|
break;
|
||||||
|
case UnmaskedStmtID:
|
||||||
|
copy = (Stmt*)new UnmaskedStmt(*(UnmaskedStmt*)this);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FATAL("Unmatched case in Stmt::Copy");
|
||||||
|
copy = this; // just to silence the compiler
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stmt *
|
||||||
|
Stmt::ReplacePolyType(const PolyType *, const Type *) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// ExprStmt
|
// ExprStmt
|
||||||
@@ -479,7 +559,8 @@ DeclStmt::TypeCheck() {
|
|||||||
// an int as the constValue later...
|
// an int as the constValue later...
|
||||||
const Type *type = vars[i].sym->type;
|
const Type *type = vars[i].sym->type;
|
||||||
if (CastType<AtomicType>(type) != NULL ||
|
if (CastType<AtomicType>(type) != NULL ||
|
||||||
CastType<EnumType>(type) != NULL) {
|
CastType<EnumType>(type) != NULL ||
|
||||||
|
CastType<PolyType>(type) != NULL) {
|
||||||
// If it's an expr list with an atomic type, we'll later issue
|
// If it's an expr list with an atomic type, we'll later issue
|
||||||
// an error. Need to leave vars[i].init as is in that case so
|
// an error. Need to leave vars[i].init as is in that case so
|
||||||
// it is in fact caught later, though.
|
// it is in fact caught later, though.
|
||||||
@@ -494,6 +575,24 @@ DeclStmt::TypeCheck() {
|
|||||||
return encounteredError ? NULL : this;
|
return encounteredError ? NULL : this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stmt *
|
||||||
|
DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
|
for (size_t i = 0; i < vars.size(); i++) {
|
||||||
|
vars[i].sym = new Symbol(*vars[i].sym);
|
||||||
|
m->symbolTable->AddVariable(vars[i].sym, false);
|
||||||
|
Symbol *s = vars[i].sym;
|
||||||
|
if (Type::EqualForReplacement(s->type->GetBaseType(), from)) {
|
||||||
|
s->type = PolyType::ReplaceType(s->type, to);
|
||||||
|
|
||||||
|
// this typecast *should* be valid after typechecking
|
||||||
|
vars[i].init = TypeConvertExpr(vars[i].init, s->type,
|
||||||
|
"initializer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
DeclStmt::Print(int indent) const {
|
DeclStmt::Print(int indent) const {
|
||||||
@@ -1470,6 +1569,17 @@ ForeachStmt::ForeachStmt(const std::vector<Symbol *> &lvs,
|
|||||||
stmts(s) {
|
stmts(s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
ForeachStmt::ForeachStmt(ForeachStmt *base)
|
||||||
|
: Stmt(base->pos, ForeachStmtID) {
|
||||||
|
dimVariables = base->dimVariables;
|
||||||
|
startExprs = base->startExprs;
|
||||||
|
endExprs = base->endExprs;
|
||||||
|
isTiled = base->isTiled;
|
||||||
|
stmts = base->stmts;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Given a uniform counter value in the memory location pointed to by
|
/* Given a uniform counter value in the memory location pointed to by
|
||||||
uniformCounterPtr, compute the corresponding set of varying counter
|
uniformCounterPtr, compute the corresponding set of varying counter
|
||||||
@@ -1713,8 +1823,10 @@ ForeachStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
// Start and end value for this loop dimension
|
// Start and end value for this loop dimension
|
||||||
llvm::Value *sv = startExprs[i]->GetValue(ctx);
|
llvm::Value *sv = startExprs[i]->GetValue(ctx);
|
||||||
llvm::Value *ev = endExprs[i]->GetValue(ctx);
|
llvm::Value *ev = endExprs[i]->GetValue(ctx);
|
||||||
if (sv == NULL || ev == NULL)
|
if (sv == NULL || ev == NULL) {
|
||||||
|
fprintf(stderr, "ev is NULL again :(\n");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
startVals.push_back(sv);
|
startVals.push_back(sv);
|
||||||
endVals.push_back(ev);
|
endVals.push_back(ev);
|
||||||
|
|
||||||
|
|||||||
3
stmt.h
3
stmt.h
@@ -70,6 +70,8 @@ public:
|
|||||||
// Stmts don't have anything to do here.
|
// Stmts don't have anything to do here.
|
||||||
virtual Stmt *Optimize();
|
virtual Stmt *Optimize();
|
||||||
virtual Stmt *TypeCheck() = 0;
|
virtual Stmt *TypeCheck() = 0;
|
||||||
|
Stmt *Copy();
|
||||||
|
Stmt *ReplacePolyType(const PolyType *polyType, const Type *replacement);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -117,6 +119,7 @@ public:
|
|||||||
|
|
||||||
Stmt *Optimize();
|
Stmt *Optimize();
|
||||||
Stmt *TypeCheck();
|
Stmt *TypeCheck();
|
||||||
|
Stmt *ReplacePolyType(const PolyType *from, const Type *to);
|
||||||
int EstimateCost() const;
|
int EstimateCost() const;
|
||||||
|
|
||||||
std::vector<VariableDeclaration> vars;
|
std::vector<VariableDeclaration> vars;
|
||||||
|
|||||||
44
sym.cpp
44
sym.cpp
@@ -95,14 +95,14 @@ SymbolTable::PopScope() {
|
|||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SymbolTable::AddVariable(Symbol *symbol) {
|
SymbolTable::AddVariable(Symbol *symbol, bool issueScopeWarning) {
|
||||||
Assert(symbol != NULL);
|
Assert(symbol != NULL);
|
||||||
|
|
||||||
// Check to see if a symbol of the same name has already been declared.
|
// Check to see if a symbol of the same name has already been declared.
|
||||||
for (int i = (int)variables.size() - 1; i >= 0; --i) {
|
for (int i = (int)variables.size() - 1; i >= 0; --i) {
|
||||||
SymbolMapType &sm = *(variables[i]);
|
SymbolMapType &sm = *(variables[i]);
|
||||||
if (sm.find(symbol->name) != sm.end()) {
|
if (sm.find(symbol->name) != sm.end()) {
|
||||||
if (i == (int)variables.size()-1) {
|
if (i == (int)variables.size()-1 && issueScopeWarning) {
|
||||||
// If a symbol of the same name was declared in the
|
// If a symbol of the same name was declared in the
|
||||||
// same scope, it's an error.
|
// same scope, it's an error.
|
||||||
Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".",
|
Error(symbol->pos, "Ignoring redeclaration of symbol \"%s\".",
|
||||||
@@ -112,9 +112,11 @@ SymbolTable::AddVariable(Symbol *symbol) {
|
|||||||
else {
|
else {
|
||||||
// Otherwise it's just shadowing something else, which
|
// Otherwise it's just shadowing something else, which
|
||||||
// is legal but dangerous..
|
// is legal but dangerous..
|
||||||
Warning(symbol->pos,
|
if (issueScopeWarning) {
|
||||||
"Symbol \"%s\" shadows symbol declared in outer scope.",
|
Warning(symbol->pos,
|
||||||
symbol->name.c_str());
|
"Symbol \"%s\" shadows symbol declared in outer scope.",
|
||||||
|
symbol->name.c_str());
|
||||||
|
}
|
||||||
(*variables.back())[symbol->name] = symbol;
|
(*variables.back())[symbol->name] = symbol;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -147,7 +149,7 @@ bool
|
|||||||
SymbolTable::AddFunction(Symbol *symbol) {
|
SymbolTable::AddFunction(Symbol *symbol) {
|
||||||
const FunctionType *ft = CastType<FunctionType>(symbol->type);
|
const FunctionType *ft = CastType<FunctionType>(symbol->type);
|
||||||
Assert(ft != NULL);
|
Assert(ft != NULL);
|
||||||
if (LookupFunction(symbol->name.c_str(), ft) != NULL)
|
if (LookupFunction(symbol->name.c_str(), ft, true) != NULL)
|
||||||
// A function of the same name and type has already been added to
|
// A function of the same name and type has already been added to
|
||||||
// the symbol table
|
// the symbol table
|
||||||
return false;
|
return false;
|
||||||
@@ -157,6 +159,14 @@ SymbolTable::AddFunction(Symbol *symbol) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SymbolTable::MapPolyFunction(std::string name, std::string polyname,
|
||||||
|
const FunctionType *type) {
|
||||||
|
std::vector<Symbol *> &polyExpansions = polyFunctions[name];
|
||||||
|
SourcePos p;
|
||||||
|
polyExpansions.push_back(new Symbol(polyname, p, type, SC_NONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
|
SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
|
||||||
@@ -175,7 +185,8 @@ SymbolTable::LookupFunction(const char *name, std::vector<Symbol *> *matches) {
|
|||||||
|
|
||||||
|
|
||||||
Symbol *
|
Symbol *
|
||||||
SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
|
SymbolTable::LookupFunction(const char *name, const FunctionType *type,
|
||||||
|
bool ignorePoly) {
|
||||||
FunctionMapType::iterator iter = functions.find(name);
|
FunctionMapType::iterator iter = functions.find(name);
|
||||||
if (iter != functions.end()) {
|
if (iter != functions.end()) {
|
||||||
std::vector<Symbol *> funcs = iter->second;
|
std::vector<Symbol *> funcs = iter->second;
|
||||||
@@ -184,9 +195,28 @@ SymbolTable::LookupFunction(const char *name, const FunctionType *type) {
|
|||||||
return funcs[j];
|
return funcs[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Try looking for a polymorphic function
|
||||||
|
if (!ignorePoly && polyFunctions[name].size() > 0) {
|
||||||
|
std::string n = name;
|
||||||
|
return new Symbol(name, polyFunctions[name][0]->pos, type);
|
||||||
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Symbol *>&
|
||||||
|
SymbolTable::LookupPolyFunction(const char *name) {
|
||||||
|
return polyFunctions[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SymbolTable::GetPolyFunctions(std::vector<std::string> *funcs) {
|
||||||
|
FunctionMapType::iterator it = polyFunctions.begin();
|
||||||
|
for (; it != polyFunctions.end(); it++) {
|
||||||
|
funcs->push_back(it->first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
SymbolTable::AddType(const char *name, const Type *type, SourcePos pos) {
|
SymbolTable::AddType(const char *name, const Type *type, SourcePos pos) {
|
||||||
|
|||||||
20
sym.h
20
sym.h
@@ -108,6 +108,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/** @brief Symbol table that holds all known symbols during parsing and compilation.
|
/** @brief Symbol table that holds all known symbols during parsing and compilation.
|
||||||
|
|
||||||
A single instance of a SymbolTable is stored in the Module class
|
A single instance of a SymbolTable is stored in the Module class
|
||||||
@@ -140,7 +141,7 @@ public:
|
|||||||
with a symbol defined at the same scope. (Symbols may shaodow
|
with a symbol defined at the same scope. (Symbols may shaodow
|
||||||
symbols in outer scopes; a warning is issued in this case, but this
|
symbols in outer scopes; a warning is issued in this case, but this
|
||||||
method still returns true.) */
|
method still returns true.) */
|
||||||
bool AddVariable(Symbol *symbol);
|
bool AddVariable(Symbol *symbol, bool issueScopeWarning=true);
|
||||||
|
|
||||||
/** Looks for a variable with the given name in the symbol table. This
|
/** Looks for a variable with the given name in the symbol table. This
|
||||||
method searches outward from the innermost scope to the outermost,
|
method searches outward from the innermost scope to the outermost,
|
||||||
@@ -159,6 +160,14 @@ public:
|
|||||||
already present in the symbol table. */
|
already present in the symbol table. */
|
||||||
bool AddFunction(Symbol *symbol);
|
bool AddFunction(Symbol *symbol);
|
||||||
|
|
||||||
|
/** Adds the given function to the list of polymorphic definitions for the
|
||||||
|
given name
|
||||||
|
@param name The name of the original function
|
||||||
|
@param type The expanded FunctionType */
|
||||||
|
|
||||||
|
void MapPolyFunction(std::string name, std::string polyname,
|
||||||
|
const FunctionType *type);
|
||||||
|
|
||||||
/** Looks for the function or functions with the given name in the
|
/** Looks for the function or functions with the given name in the
|
||||||
symbol name. If a function has been overloaded and multiple
|
symbol name. If a function has been overloaded and multiple
|
||||||
definitions are present for a given function name, all of them will
|
definitions are present for a given function name, all of them will
|
||||||
@@ -172,7 +181,12 @@ public:
|
|||||||
in the symbol table.
|
in the symbol table.
|
||||||
|
|
||||||
@return pointer to matching Symbol; NULL if none is found. */
|
@return pointer to matching Symbol; NULL if none is found. */
|
||||||
Symbol *LookupFunction(const char *name, const FunctionType *type);
|
Symbol *LookupFunction(const char *name, const FunctionType *type,
|
||||||
|
bool ignorePoly = false);
|
||||||
|
|
||||||
|
std::vector<Symbol *>& LookupPolyFunction(const char *name);
|
||||||
|
|
||||||
|
void GetPolyFunctions(std::vector<std::string> *funcs);
|
||||||
|
|
||||||
/** Returns all of the functions in the symbol table that match the given
|
/** Returns all of the functions in the symbol table that match the given
|
||||||
predicate.
|
predicate.
|
||||||
@@ -276,6 +290,8 @@ private:
|
|||||||
typedef std::map<std::string, std::vector<Symbol *> > FunctionMapType;
|
typedef std::map<std::string, std::vector<Symbol *> > FunctionMapType;
|
||||||
FunctionMapType functions;
|
FunctionMapType functions;
|
||||||
|
|
||||||
|
FunctionMapType polyFunctions;
|
||||||
|
|
||||||
/** Type definitions can't currently be scoped.
|
/** Type definitions can't currently be scoped.
|
||||||
*/
|
*/
|
||||||
typedef std::map<std::string, const Type *> TypeMapType;
|
typedef std::map<std::string, const Type *> TypeMapType;
|
||||||
|
|||||||
13
tests_ispcpp/Makefile
Normal file
13
tests_ispcpp/Makefile
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
CXX=g++
|
||||||
|
CXXFLAGS=-std=c++11 -O2
|
||||||
|
|
||||||
|
ISPC=../ispc
|
||||||
|
ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64
|
||||||
|
|
||||||
|
%.out : %.cpp %.o
|
||||||
|
$(CXX) $(CXXFLAGS) -o $@ $^
|
||||||
|
|
||||||
|
$ : $.o
|
||||||
|
|
||||||
|
%.o : %.ispc
|
||||||
|
$(ISPC) $(ISPCFLAGS) -h $*.h -o $*.o $<
|
||||||
6
tests_ispcpp/error_0.ispc
Normal file
6
tests_ispcpp/error_0.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//@error
|
||||||
|
//assigning mismatched polymorphic types
|
||||||
|
|
||||||
|
export void foo(uniform floating$0 bar) {
|
||||||
|
floating$1 baz = bar;
|
||||||
|
}
|
||||||
6
tests_ispcpp/error_1.ispc
Normal file
6
tests_ispcpp/error_1.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//@error
|
||||||
|
//assigning mismatched polymorphic types
|
||||||
|
|
||||||
|
export void foo(floating$0 bar) {
|
||||||
|
floating baz = bar;
|
||||||
|
}
|
||||||
6
tests_ispcpp/error_2.ispc
Normal file
6
tests_ispcpp/error_2.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//@error
|
||||||
|
//assigning mismatched polymorphic types
|
||||||
|
|
||||||
|
export void foo(uniform floating$0 bar) {
|
||||||
|
integer baz = bar;
|
||||||
|
}
|
||||||
6
tests_ispcpp/error_3.ispc
Normal file
6
tests_ispcpp/error_3.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
//@error
|
||||||
|
//assigning mismatched polymorphic types
|
||||||
|
|
||||||
|
export void foo(number$0 bar) {
|
||||||
|
integer baz = bar;
|
||||||
|
}
|
||||||
19
tests_ispcpp/error_4.ispc
Normal file
19
tests_ispcpp/error_4.ispc
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
//@error
|
||||||
|
// cannot determine return type for mult
|
||||||
|
|
||||||
|
|
||||||
|
floating mult(floating$0 x, floating$1 y) {
|
||||||
|
return x * y;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void saxpy(uniform int N,
|
||||||
|
uniform floating$0 scale,
|
||||||
|
uniform floating$1 X[],
|
||||||
|
uniform floating$1 Y[],
|
||||||
|
uniform floating$2 result[])
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... N) {
|
||||||
|
floating$2 tmp = mult(scale, X[i]) + Y[i];
|
||||||
|
result[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
tests_ispcpp/function.ispc
Normal file
17
tests_ispcpp/function.ispc
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
floating saxpy_helper(floating scale,
|
||||||
|
floating<0> x,
|
||||||
|
floating<0> y) {
|
||||||
|
return scale * x + y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export void saxpy(uniform int N,
|
||||||
|
uniform floating<0> scale,
|
||||||
|
uniform floating<1> X[],
|
||||||
|
uniform floating<1> Y[],
|
||||||
|
uniform floating<2> result[])
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... N) {
|
||||||
|
result[i] = saxpy_helper(scale, X[i], Y[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "hello.ispc.h"
|
#include "hello.h"
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
float A[100];
|
float A[100];
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
export void saxpy(uniform int N,
|
export void saxpy(uniform int N,
|
||||||
uniform floating<0> scale,
|
uniform floating$0 scale,
|
||||||
uniform floating<1> X[],
|
uniform floating$1 X[],
|
||||||
uniform floating<1> Y[],
|
uniform floating$1 Y[],
|
||||||
uniform floating<2> result[])
|
uniform floating$2 result[])
|
||||||
{
|
{
|
||||||
foreach (i = 0 ... N) {
|
foreach (i = 0 ... N) {
|
||||||
floating<2> tmp = scale * X[i] + Y[i];
|
floating$2 tmp = scale * X[i] + Y[i];
|
||||||
result[i] = tmp;
|
result[i] = tmp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
20
tests_ispcpp/simple.cpp
Normal file
20
tests_ispcpp/simple.cpp
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "simple.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
double A[256];
|
||||||
|
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
A[i] = i / 11.;
|
||||||
|
}
|
||||||
|
|
||||||
|
ispc::foo(256, (double*)&A);
|
||||||
|
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
printf("%f\n", A[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
6
tests_ispcpp/simple.ispc
Normal file
6
tests_ispcpp/simple.ispc
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export void foo(uniform int N, uniform floating$1 X[])
|
||||||
|
{
|
||||||
|
foreach (i = 0 ... N) {
|
||||||
|
X[i] = X[i] + 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
27
tests_ispcpp/varying.cpp
Normal file
27
tests_ispcpp/varying.cpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "varying.h"
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
float A[256];
|
||||||
|
double B[256];
|
||||||
|
double outA[256];
|
||||||
|
double outB[256];
|
||||||
|
|
||||||
|
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
A[i] = 1. / (i+1);
|
||||||
|
B[i] = 1. / (i+1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ispc::square(256, (float*)&A, (double*)&outA);
|
||||||
|
|
||||||
|
ispc::square(256, (double*)&B, (double*)&outB);
|
||||||
|
|
||||||
|
for (int i=0; i<256; i++) {
|
||||||
|
printf("float: %.16f\tdouble: %.16f\n", outA[i], outB[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
tests_ispcpp/varying.ispc
Normal file
14
tests_ispcpp/varying.ispc
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
floating foo(const uniform int a, floating b) {
|
||||||
|
floating out = b;
|
||||||
|
for (int i = 1; i<a; i++) {
|
||||||
|
out *= b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
export void square(uniform int N, uniform floating b[], uniform double out[]) {
|
||||||
|
foreach (i = 0 ... N) {
|
||||||
|
out[i] = foo(2, b[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
532
type.cpp
532
type.cpp
@@ -247,6 +247,20 @@ Type::IsVoidType() const {
|
|||||||
return EqualIgnoringConst(this, AtomicType::Void);
|
return EqualIgnoringConst(this, AtomicType::Void);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type::IsPolymorphicType() const {
|
||||||
|
const FunctionType *ft = CastType<FunctionType>(this);
|
||||||
|
if (ft) {
|
||||||
|
for (int i=0; i<ft->GetNumParameters(); i++) {
|
||||||
|
if (ft->GetParameterType(i)->IsPolymorphicType())
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return (CastType<PolyType>(GetBaseType()) != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
AtomicType::IsFloatType() const {
|
AtomicType::IsFloatType() const {
|
||||||
return (basicType == TYPE_FLOAT || basicType == TYPE_DOUBLE);
|
return (basicType == TYPE_FLOAT || basicType == TYPE_DOUBLE);
|
||||||
@@ -673,6 +687,454 @@ llvm::DIType *AtomicType::GetDIType(llvm::DIScope *scope) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// PolyType
|
||||||
|
|
||||||
|
const PolyType *PolyType::UniformInteger =
|
||||||
|
new PolyType(PolyType::TYPE_INTEGER, Variability::Uniform, false);
|
||||||
|
const PolyType *PolyType::VaryingInteger =
|
||||||
|
new PolyType(PolyType::TYPE_INTEGER, Variability::Varying, false);
|
||||||
|
const PolyType *PolyType::UniformFloating =
|
||||||
|
new PolyType(PolyType::TYPE_FLOATING, Variability::Uniform, false);
|
||||||
|
const PolyType *PolyType::VaryingFloating =
|
||||||
|
new PolyType(PolyType::TYPE_FLOATING, Variability::Varying, false);
|
||||||
|
const PolyType *PolyType::UniformNumber =
|
||||||
|
new PolyType(PolyType::TYPE_NUMBER, Variability::Uniform, false);
|
||||||
|
const PolyType *PolyType::VaryingNumber =
|
||||||
|
new PolyType(PolyType::TYPE_NUMBER, Variability::Varying, false);
|
||||||
|
|
||||||
|
const Type *
|
||||||
|
PolyType::ReplaceType(const Type *from, const Type *to) {
|
||||||
|
const Type *t = to;
|
||||||
|
|
||||||
|
if (from->IsPointerType()) {
|
||||||
|
t = new PointerType(to,
|
||||||
|
from->GetVariability(),
|
||||||
|
from->IsConstType());
|
||||||
|
} else if (from->IsArrayType()) {
|
||||||
|
t = new ArrayType(to,
|
||||||
|
CastType<ArrayType>(from)->GetElementCount());
|
||||||
|
} else if (from->IsReferenceType()) {
|
||||||
|
t = new ReferenceType(to);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from->IsVaryingType())
|
||||||
|
t = t->GetAsVaryingType();
|
||||||
|
|
||||||
|
if (g->debugPrint) {
|
||||||
|
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
|
||||||
|
from->GetString().c_str(),
|
||||||
|
t->GetString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::Less(const Type *a, const Type *b) {
|
||||||
|
const PolyType *pa = CastType<PolyType>(a->GetBaseType());
|
||||||
|
const PolyType *pb = CastType<PolyType>(b->GetBaseType());
|
||||||
|
|
||||||
|
if (!pa || !pb) {
|
||||||
|
char buf[1024];
|
||||||
|
snprintf(buf, 1024, "Calling lPolyTypeLess on non-polymorphic types"
|
||||||
|
"\"%s\" and \"%s\"\n",
|
||||||
|
a->GetString().c_str(), b->GetString().c_str());
|
||||||
|
FATAL(buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (pa->restriction < pb->restriction)
|
||||||
|
return true;
|
||||||
|
if (pa->restriction > pb->restriction)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (pa->GetQuant() < pb->GetQuant())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyType::PolyType(PolyRestriction r, Variability v, bool ic)
|
||||||
|
: Type(POLY_TYPE), restriction(r), variability(v), isConst(ic), quant(-1) {
|
||||||
|
asOtherConstType = NULL;
|
||||||
|
asUniformType = asVaryingType = NULL;
|
||||||
|
expandedTypes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolyType::PolyType(PolyRestriction r, Variability v, bool ic, int q)
|
||||||
|
: Type(POLY_TYPE), restriction(r), variability(v), isConst(ic), quant(q) {
|
||||||
|
asOtherConstType = NULL;
|
||||||
|
asUniformType = asVaryingType = NULL;
|
||||||
|
expandedTypes = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Variability
|
||||||
|
PolyType::GetVariability() const {
|
||||||
|
return variability;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
PolyType::GetQuant() const {
|
||||||
|
return quant;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::IsFloatType() const {
|
||||||
|
return (restriction == TYPE_FLOATING);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::IsIntType() const {
|
||||||
|
return (restriction == TYPE_INTEGER);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::IsUnsignedType() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::IsBoolType() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::IsConstType() const {
|
||||||
|
return isConst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsUnsignedType() const {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsConstType() const {
|
||||||
|
if (isConst == true)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (asOtherConstType == NULL) {
|
||||||
|
asOtherConstType = new PolyType(restriction, variability, true, quant);
|
||||||
|
asOtherConstType->asOtherConstType = this;
|
||||||
|
}
|
||||||
|
return asOtherConstType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsNonConstType() const {
|
||||||
|
if (isConst == false)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (asOtherConstType == NULL) {
|
||||||
|
asOtherConstType = new PolyType(restriction, variability, false, quant);
|
||||||
|
asOtherConstType->asOtherConstType = this;
|
||||||
|
}
|
||||||
|
return asOtherConstType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetBaseType() const {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsVaryingType() const {
|
||||||
|
if (variability == Variability::Varying)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (asVaryingType == NULL) {
|
||||||
|
asVaryingType = new PolyType(restriction, Variability::Varying,
|
||||||
|
isConst, quant);
|
||||||
|
if (variability == Variability::Uniform)
|
||||||
|
asVaryingType->asUniformType = this;
|
||||||
|
}
|
||||||
|
return asVaryingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsUniformType() const {
|
||||||
|
if (variability == Variability::Uniform)
|
||||||
|
return this;
|
||||||
|
|
||||||
|
if (asUniformType == NULL) {
|
||||||
|
asUniformType = new PolyType(restriction, Variability::Uniform,
|
||||||
|
isConst, quant);
|
||||||
|
if (variability == Variability::Varying)
|
||||||
|
asUniformType->asVaryingType = this;
|
||||||
|
}
|
||||||
|
return asUniformType;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<AtomicType *>::iterator
|
||||||
|
PolyType::ExpandBegin() const {
|
||||||
|
if (expandedTypes)
|
||||||
|
return expandedTypes->begin();
|
||||||
|
|
||||||
|
expandedTypes = new std::vector<AtomicType *>();
|
||||||
|
|
||||||
|
if (restriction == TYPE_INTEGER || restriction == TYPE_NUMBER) {
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_INT8, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_UINT8, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_INT16, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_UINT16, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_INT32, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_UINT32, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_INT64, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_UINT64, variability, isConst));
|
||||||
|
}
|
||||||
|
if (restriction == TYPE_FLOATING || restriction == TYPE_NUMBER) {
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_FLOAT, variability, isConst));
|
||||||
|
expandedTypes->push_back(new AtomicType(AtomicType::TYPE_DOUBLE, variability, isConst));
|
||||||
|
}
|
||||||
|
|
||||||
|
return expandedTypes->begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<AtomicType *>::iterator
|
||||||
|
PolyType::ExpandEnd() const {
|
||||||
|
Assert(expandedTypes != NULL);
|
||||||
|
|
||||||
|
return expandedTypes->end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsUnboundVariabilityType() const {
|
||||||
|
if (variability == Variability::Unbound)
|
||||||
|
return this;
|
||||||
|
return new PolyType(restriction, Variability::Unbound, isConst, quant);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::GetAsSOAType(int width) const {
|
||||||
|
if (variability == Variability(Variability::SOA, width))
|
||||||
|
return this;
|
||||||
|
return new PolyType(restriction, Variability(Variability::SOA, width),
|
||||||
|
isConst, quant);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::ResolveUnboundVariability(Variability v) const {
|
||||||
|
Assert(v != Variability::Unbound);
|
||||||
|
if (variability != Variability::Unbound)
|
||||||
|
return this;
|
||||||
|
return new PolyType(restriction, v, isConst, quant);
|
||||||
|
}
|
||||||
|
|
||||||
|
const PolyType *
|
||||||
|
PolyType::Quantify(int q) const {
|
||||||
|
return new PolyType(restriction, variability, isConst, q);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
PolyType::CanBeType(const Type *t) const {
|
||||||
|
const PolyType *pt = CastType<PolyType>(t);
|
||||||
|
if (pt) {
|
||||||
|
return (restriction == pt->restriction ||
|
||||||
|
restriction == TYPE_NUMBER);
|
||||||
|
}
|
||||||
|
|
||||||
|
const AtomicType *at = CastType<AtomicType>(t);
|
||||||
|
|
||||||
|
if (at) {
|
||||||
|
switch (restriction) {
|
||||||
|
case TYPE_INTEGER:
|
||||||
|
return at->IsIntType();
|
||||||
|
case TYPE_FLOATING:
|
||||||
|
return at->IsFloatType();
|
||||||
|
case TYPE_NUMBER:
|
||||||
|
return at->IsIntType() || at->IsFloatType();
|
||||||
|
default:
|
||||||
|
FATAL("Unmatched case for polymorphic restriction");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// not an atomic type or polymorphic type
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PolyType::GetString() const {
|
||||||
|
std::string ret;
|
||||||
|
if (isConst) ret += "const ";
|
||||||
|
|
||||||
|
ret += variability.GetString();
|
||||||
|
ret += " ";
|
||||||
|
|
||||||
|
switch (restriction) {
|
||||||
|
case TYPE_INTEGER: ret += "integer"; break;
|
||||||
|
case TYPE_FLOATING: ret += "floating"; break;
|
||||||
|
case TYPE_NUMBER: ret += "number"; break;
|
||||||
|
default: FATAL("Logic error in PolyType::GetString()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (quant >= 0) {
|
||||||
|
ret += "$";
|
||||||
|
ret += std::to_string(quant);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PolyType::Mangle() const {
|
||||||
|
std::string ret;
|
||||||
|
if (isConst) ret += "C";
|
||||||
|
ret += variability.MangleString();
|
||||||
|
|
||||||
|
switch (restriction) {
|
||||||
|
case TYPE_INTEGER: ret += "Z"; break;
|
||||||
|
case TYPE_FLOATING: ret += "Q"; break;
|
||||||
|
case TYPE_NUMBER: ret += "R"; break;
|
||||||
|
default: FATAL("Logic error in PolyType::Mangle()");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string
|
||||||
|
PolyType::GetCDeclaration(const std::string &name) const {
|
||||||
|
std::string ret;
|
||||||
|
if (variability == Variability::Unbound) {
|
||||||
|
Assert(m->errorCount > 0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (isConst) ret += "const ";
|
||||||
|
|
||||||
|
switch (restriction) {
|
||||||
|
case TYPE_INTEGER: ret += "int32_t"; break;
|
||||||
|
case TYPE_FLOATING: ret += "double"; break;
|
||||||
|
case TYPE_NUMBER: ret += "double"; break;
|
||||||
|
default: FATAL("Logic error in PolyType::GetCDeclaration()");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lShouldPrintName(name)) {
|
||||||
|
ret += " ";
|
||||||
|
ret += name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (variability == Variability::SOA) {
|
||||||
|
char buf[32];
|
||||||
|
sprintf(buf, "[%d]", variability.soaWidth);
|
||||||
|
ret += buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
llvm::Type *
|
||||||
|
PolyType::LLVMType(llvm::LLVMContext *ctx) const {
|
||||||
|
Assert(variability.type != Variability::Unbound);
|
||||||
|
bool isUniform = (variability == Variability::Uniform);
|
||||||
|
bool isVarying = (variability == Variability::Varying);
|
||||||
|
|
||||||
|
if (isUniform || isVarying) {
|
||||||
|
switch (restriction) {
|
||||||
|
case TYPE_INTEGER:
|
||||||
|
return isUniform ? LLVMTypes::Int32Type : LLVMTypes::Int32VectorType;
|
||||||
|
case TYPE_FLOATING:
|
||||||
|
case TYPE_NUMBER:
|
||||||
|
return isUniform ? LLVMTypes::DoubleType : LLVMTypes::DoubleVectorType;
|
||||||
|
default:
|
||||||
|
FATAL("logic error in PolyType::LLVMType");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ArrayType at(GetAsUniformType(), variability.soaWidth);
|
||||||
|
return at.LLVMType(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
|
||||||
|
llvm::DIType PolyType::GetDIType(llvm::DIDescriptor scope) const {
|
||||||
|
#else //LLVM 3.7++
|
||||||
|
llvm::DIType *PolyType::GetDIType(llvm::DIScope *scope) const {
|
||||||
|
#endif
|
||||||
|
Assert(variability.type != Variability::Unbound);
|
||||||
|
|
||||||
|
if (variability.type == Variability::Uniform) {
|
||||||
|
switch (restriction) {
|
||||||
|
#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_9
|
||||||
|
case TYPE_INTEGER:
|
||||||
|
return m->diBuilder->createBasicType("int32", 32 /* size */, 32 /* align */,
|
||||||
|
llvm::dwarf::DW_ATE_signed);
|
||||||
|
break;
|
||||||
|
case TYPE_FLOATING:
|
||||||
|
case TYPE_NUMBER:
|
||||||
|
return m->diBuilder->createBasicType("double", 64 /* size */, 64 /* align */,
|
||||||
|
llvm::dwarf::DW_ATE_float);
|
||||||
|
break;
|
||||||
|
#else // LLVM 4.0+
|
||||||
|
case TYPE_INTEGER:
|
||||||
|
return m->diBuilder->createBasicType("int32", 32 /* size */,
|
||||||
|
llvm::dwarf::DW_ATE_signed);
|
||||||
|
break;
|
||||||
|
case TYPE_FLOATING:
|
||||||
|
case TYPE_NUMBER:
|
||||||
|
return m->diBuilder->createBasicType("double", 64 /* size */,
|
||||||
|
llvm::dwarf::DW_ATE_float);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
default:
|
||||||
|
FATAL("unhandled basic type in PolyType::GetDIType()");
|
||||||
|
#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
|
||||||
|
return llvm::DIType();
|
||||||
|
#else //LLVM 3.7+
|
||||||
|
return NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (variability == Variability::Varying) {
|
||||||
|
#if ISPC_LLVM_VERSION == ISPC_LLVM_3_2
|
||||||
|
llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth()-1);
|
||||||
|
#elif ISPC_LLVM_VERSION > ISPC_VERSION_3_2 && ISPC_LLVM_VERSION <= ISPC_LLVM_3_5
|
||||||
|
llvm::Value *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth());
|
||||||
|
#else // LLVM 3.6+
|
||||||
|
llvm::Metadata *sub = m->diBuilder->getOrCreateSubrange(0, g->target->getVectorWidth());
|
||||||
|
#endif
|
||||||
|
#if ISPC_LLVM_VERSION > ISPC_VERSION_3_2 && ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
|
||||||
|
llvm::DIArray subArray = m->diBuilder->getOrCreateArray(sub);
|
||||||
|
llvm::DIType unifType = GetAsUniformType()->GetDIType(scope);
|
||||||
|
uint64_t size = unifType.getSizeInBits() * g->target->getVectorWidth();
|
||||||
|
uint64_t align = unifType.getAlignInBits() * g->target->getVectorWidth();
|
||||||
|
#else // LLVM 3.7+
|
||||||
|
llvm::DINodeArray subArray = m->diBuilder->getOrCreateArray(sub);
|
||||||
|
llvm::DIType *unifType = GetAsUniformType()->GetDIType(scope);
|
||||||
|
//llvm::DebugNodeArray subArray = m->diBuilder->getOrCreateArray(sub);
|
||||||
|
//llvm::MDType *unifType = GetAsUniformType()->GetDIType(scope);
|
||||||
|
uint64_t size = unifType->getSizeInBits() * g->target->getVectorWidth();
|
||||||
|
uint64_t align = unifType->getAlignInBits()* g->target->getVectorWidth();
|
||||||
|
#endif
|
||||||
|
return m->diBuilder->createVectorType(size, align, unifType, subArray);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Assert(variability == Variability::SOA);
|
||||||
|
ArrayType at(GetAsUniformType(), variability.soaWidth);
|
||||||
|
return at.GetDIType(scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// EnumType
|
// EnumType
|
||||||
@@ -3134,6 +3596,34 @@ FunctionType::GetCDeclaration(const std::string &fname) const {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
FunctionType::GetCCall(const std::string &fname) const {
|
||||||
|
std::string ret;
|
||||||
|
ret += fname;
|
||||||
|
ret += "(";
|
||||||
|
for (unsigned int i = 0; i < paramTypes.size(); ++i) {
|
||||||
|
const Type *type = paramTypes[i];
|
||||||
|
|
||||||
|
// Convert pointers to arrays to unsized arrays, which are more clear
|
||||||
|
// to print out for multidimensional arrays (i.e. "float foo[][4] "
|
||||||
|
// versus "float (foo *)[4]").
|
||||||
|
const PointerType *pt = CastType<PointerType>(type);
|
||||||
|
if (pt != NULL &&
|
||||||
|
CastType<ArrayType>(pt->GetBaseType()) != NULL) {
|
||||||
|
type = new ArrayType(pt->GetBaseType(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (paramNames[i] != "")
|
||||||
|
ret += paramNames[i];
|
||||||
|
else
|
||||||
|
FATAL("Exporting a polymorphic function with incomplete arguments");
|
||||||
|
if (i != paramTypes.size() - 1)
|
||||||
|
ret += ", ";
|
||||||
|
}
|
||||||
|
ret += ")";
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
FunctionType::GetCDeclarationForDispatch(const std::string &fname) const {
|
FunctionType::GetCDeclarationForDispatch(const std::string &fname) const {
|
||||||
@@ -3554,6 +4044,24 @@ Type::MoreGeneralType(const Type *t0, const Type *t1, SourcePos pos, const char
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PolyType *pyt0 = CastType<PolyType>(t0);
|
||||||
|
const PolyType *pyt1 = CastType<PolyType>(t1);
|
||||||
|
|
||||||
|
if (pyt0 || pyt1) {
|
||||||
|
// one of the types is polymorphic
|
||||||
|
if (pyt0 && pyt0->CanBeType(t1)) {
|
||||||
|
return pyt0;
|
||||||
|
} else if (pyt1 && pyt1->CanBeType(t0)) {
|
||||||
|
return pyt1;
|
||||||
|
} else {
|
||||||
|
// polymorphic type cannot represent the other type
|
||||||
|
// this is most likely bad
|
||||||
|
Error(pos, "Polymorphic type incompatible for \"%s\" and \"%s\""
|
||||||
|
" for %s.", t0->GetString().c_str(),
|
||||||
|
t1->GetString().c_str(), reason);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now all we can do is promote atomic types...
|
// Now all we can do is promote atomic types...
|
||||||
if (at0 == NULL || at1 == NULL) {
|
if (at0 == NULL || at1 == NULL) {
|
||||||
Assert(reason != NULL);
|
Assert(reason != NULL);
|
||||||
@@ -3572,7 +4080,8 @@ bool
|
|||||||
Type::IsBasicType(const Type *type) {
|
Type::IsBasicType(const Type *type) {
|
||||||
return (CastType<AtomicType>(type) != NULL ||
|
return (CastType<AtomicType>(type) != NULL ||
|
||||||
CastType<EnumType>(type) != NULL ||
|
CastType<EnumType>(type) != NULL ||
|
||||||
CastType<PointerType>(type) != NULL);
|
CastType<PointerType>(type) != NULL ||
|
||||||
|
CastType<PolyType>(type) != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -3592,6 +4101,14 @@ lCheckTypeEquality(const Type *a, const Type *b, bool ignoreConst) {
|
|||||||
(ata->GetVariability() == atb->GetVariability()));
|
(ata->GetVariability() == atb->GetVariability()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PolyType *pyta = CastType<PolyType>(a);
|
||||||
|
const PolyType *pytb = CastType<PolyType>(b);
|
||||||
|
if (pyta != NULL && pytb != NULL) {
|
||||||
|
return ((pyta->restriction == pytb->restriction) &&
|
||||||
|
(pyta->GetVariability() == pytb->GetVariability()) &&
|
||||||
|
(pyta->GetQuant() == pytb->GetQuant()));
|
||||||
|
}
|
||||||
|
|
||||||
// For all of the other types, we need to see if we have the same two
|
// For all of the other types, we need to see if we have the same two
|
||||||
// general types. If so, then we dig into the details of the type and
|
// general types. If so, then we dig into the details of the type and
|
||||||
// see if all of the relevant bits are equal...
|
// see if all of the relevant bits are equal...
|
||||||
@@ -3688,3 +4205,16 @@ bool
|
|||||||
Type::EqualIgnoringConst(const Type *a, const Type *b) {
|
Type::EqualIgnoringConst(const Type *a, const Type *b) {
|
||||||
return lCheckTypeEquality(a, b, true);
|
return lCheckTypeEquality(a, b, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Type::EqualForReplacement(const Type *a, const Type *b) {
|
||||||
|
const PolyType *pa = CastType<PolyType>(a);
|
||||||
|
const PolyType *pb = CastType<PolyType>(b);
|
||||||
|
|
||||||
|
|
||||||
|
if (!pa || !pb)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return pa->restriction == pb->restriction &&
|
||||||
|
pa->GetQuant() == pb->GetQuant();
|
||||||
|
}
|
||||||
|
|||||||
89
type.h
89
type.h
@@ -89,7 +89,8 @@ enum TypeId {
|
|||||||
STRUCT_TYPE, // 5
|
STRUCT_TYPE, // 5
|
||||||
UNDEFINED_STRUCT_TYPE, // 6
|
UNDEFINED_STRUCT_TYPE, // 6
|
||||||
REFERENCE_TYPE, // 7
|
REFERENCE_TYPE, // 7
|
||||||
FUNCTION_TYPE // 8
|
FUNCTION_TYPE, // 8
|
||||||
|
POLY_TYPE // 9
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -132,6 +133,9 @@ public:
|
|||||||
/** Returns true if the underlying type is either a pointer or an array */
|
/** Returns true if the underlying type is either a pointer or an array */
|
||||||
bool IsVoidType() const;
|
bool IsVoidType() const;
|
||||||
|
|
||||||
|
/** Returns true if the underlying type is polymorphic */
|
||||||
|
bool IsPolymorphicType() const;
|
||||||
|
|
||||||
/** Returns true if this type is 'const'-qualified. */
|
/** Returns true if this type is 'const'-qualified. */
|
||||||
virtual bool IsConstType() const = 0;
|
virtual bool IsConstType() const = 0;
|
||||||
|
|
||||||
@@ -240,6 +244,8 @@ public:
|
|||||||
the same (ignoring const-ness of the type), false otherwise. */
|
the same (ignoring const-ness of the type), false otherwise. */
|
||||||
static bool EqualIgnoringConst(const Type *a, const Type *b);
|
static bool EqualIgnoringConst(const Type *a, const Type *b);
|
||||||
|
|
||||||
|
static bool EqualForReplacement(const Type *a, const Type *b);
|
||||||
|
|
||||||
/** Given two types, returns the least general Type that is more general
|
/** Given two types, returns the least general Type that is more general
|
||||||
than both of them. (i.e. that can represent their values without
|
than both of them. (i.e. that can represent their values without
|
||||||
any loss of data.) If there is no such Type, return NULL.
|
any loss of data.) If there is no such Type, return NULL.
|
||||||
@@ -356,14 +362,84 @@ public:
|
|||||||
static const AtomicType *UniformDouble, *VaryingDouble;
|
static const AtomicType *UniformDouble, *VaryingDouble;
|
||||||
static const AtomicType *Void;
|
static const AtomicType *Void;
|
||||||
|
|
||||||
|
AtomicType(BasicType basicType, Variability v, bool isConst);
|
||||||
private:
|
private:
|
||||||
const Variability variability;
|
const Variability variability;
|
||||||
const bool isConst;
|
const bool isConst;
|
||||||
AtomicType(BasicType basicType, Variability v, bool isConst);
|
|
||||||
|
|
||||||
mutable const AtomicType *asOtherConstType, *asUniformType, *asVaryingType;
|
mutable const AtomicType *asOtherConstType, *asUniformType, *asVaryingType;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class PolyType : public Type {
|
||||||
|
public:
|
||||||
|
Variability GetVariability() const;
|
||||||
|
int GetQuant() const;
|
||||||
|
|
||||||
|
bool IsBoolType() const;
|
||||||
|
bool IsFloatType() const;
|
||||||
|
bool IsIntType() const;
|
||||||
|
bool IsUnsignedType() const;
|
||||||
|
bool IsConstType() const;
|
||||||
|
|
||||||
|
const PolyType *GetBaseType() const;
|
||||||
|
const PolyType *GetAsUniformType() const;
|
||||||
|
const PolyType *GetAsVaryingType() const;
|
||||||
|
const PolyType *GetAsUnboundVariabilityType() const;
|
||||||
|
const PolyType *GetAsSOAType(int width) const;
|
||||||
|
|
||||||
|
const PolyType *ResolveUnboundVariability(Variability v) const;
|
||||||
|
const PolyType *GetAsUnsignedType() const;
|
||||||
|
const PolyType *GetAsConstType() const;
|
||||||
|
const PolyType *GetAsNonConstType() const;
|
||||||
|
|
||||||
|
const PolyType *Quantify(int quant) const;
|
||||||
|
|
||||||
|
bool CanBeType(const Type *t) const;
|
||||||
|
|
||||||
|
std::string GetString() const;
|
||||||
|
std::string Mangle() const;
|
||||||
|
std::string GetCDeclaration(const std::string &name) const;
|
||||||
|
|
||||||
|
llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
|
||||||
|
#if ISPC_LLVM_VERSION <= ISPC_LLVM_3_6
|
||||||
|
llvm::DIType GetDIType(llvm::DIDescriptor scope) const;
|
||||||
|
#else // LLVM 3.7++
|
||||||
|
llvm::DIType *GetDIType(llvm::DIScope *scope) const;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
enum PolyRestriction {
|
||||||
|
TYPE_INTEGER,
|
||||||
|
TYPE_FLOATING,
|
||||||
|
TYPE_NUMBER
|
||||||
|
};
|
||||||
|
|
||||||
|
const PolyRestriction restriction;
|
||||||
|
|
||||||
|
static const Type * ReplaceType(const Type *from, const Type *to);
|
||||||
|
|
||||||
|
static bool Less(const Type *a, const Type *b);
|
||||||
|
|
||||||
|
|
||||||
|
static const PolyType *UniformInteger, *VaryingInteger;
|
||||||
|
static const PolyType *UniformFloating, *VaryingFloating;
|
||||||
|
static const PolyType *UniformNumber, *VaryingNumber;
|
||||||
|
|
||||||
|
// Returns the list of AtomicTypes that are valid instantiations of the
|
||||||
|
// polymorphic type
|
||||||
|
const std::vector<AtomicType *>::iterator ExpandBegin() const;
|
||||||
|
const std::vector<AtomicType *>::iterator ExpandEnd() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const Variability variability;
|
||||||
|
const bool isConst;
|
||||||
|
const int quant;
|
||||||
|
PolyType(PolyRestriction type, Variability v, bool isConst);
|
||||||
|
PolyType(PolyRestriction type, Variability v, bool isConst, int quant);
|
||||||
|
|
||||||
|
mutable const PolyType *asOtherConstType, *asUniformType, *asVaryingType;
|
||||||
|
mutable std::vector<AtomicType *> *expandedTypes;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** @brief Type implementation for enumerated types
|
/** @brief Type implementation for enumerated types
|
||||||
*/
|
*/
|
||||||
@@ -912,6 +988,7 @@ public:
|
|||||||
std::string GetString() const;
|
std::string GetString() const;
|
||||||
std::string Mangle() const;
|
std::string Mangle() const;
|
||||||
std::string GetCDeclaration(const std::string &fname) const;
|
std::string GetCDeclaration(const std::string &fname) const;
|
||||||
|
std::string GetCCall(const std::string &fname) const;
|
||||||
std::string GetCDeclarationForDispatch(const std::string &fname) const;
|
std::string GetCDeclarationForDispatch(const std::string &fname) const;
|
||||||
|
|
||||||
llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
|
llvm::Type *LLVMType(llvm::LLVMContext *ctx) const;
|
||||||
@@ -1002,6 +1079,14 @@ CastType(const Type *type) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <> inline const PolyType *
|
||||||
|
CastType(const Type *type) {
|
||||||
|
if (type != NULL && type->typeId == POLY_TYPE)
|
||||||
|
return (const PolyType *)type;
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
template <> inline const EnumType *
|
template <> inline const EnumType *
|
||||||
CastType(const Type *type) {
|
CastType(const Type *type) {
|
||||||
if (type != NULL && type->typeId == ENUM_TYPE)
|
if (type != NULL && type->typeId == ENUM_TYPE)
|
||||||
|
|||||||
Reference in New Issue
Block a user