Fixed issue with aliasing local variables
ISPC++ now produces valid code, or an appropriate error message, for all of my test cases.
This commit is contained in:
29
expr.cpp
29
expr.cpp
@@ -8099,6 +8099,11 @@ SymbolExpr::ReplacePolyType(const PolyType *from, const Type *to) {
|
|||||||
if (!symbol)
|
if (!symbol)
|
||||||
return NULL;
|
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)) {
|
if (Type::EqualForReplacement(symbol->type->GetBaseType(), from)) {
|
||||||
symbol->type = PolyType::ReplaceType(symbol->type, to);
|
symbol->type = PolyType::ReplaceType(symbol->type, to);
|
||||||
@@ -8176,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 {
|
||||||
@@ -8422,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.
|
||||||
@@ -8548,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);
|
||||||
|
|||||||
1
expr.h
1
expr.h
@@ -761,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;
|
||||||
|
|||||||
40
func.cpp
40
func.cpp
@@ -90,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;
|
||||||
|
|
||||||
@@ -98,6 +98,7 @@ Function::Function(Symbol *s, Stmt *c) {
|
|||||||
Assert(maskSymbol != NULL);
|
Assert(maskSymbol != NULL);
|
||||||
|
|
||||||
if (code != NULL) {
|
if (code != NULL) {
|
||||||
|
if (typecheck) {
|
||||||
code = TypeCheck(code);
|
code = TypeCheck(code);
|
||||||
|
|
||||||
if (code != NULL && g->debugPrint) {
|
if (code != NULL && g->debugPrint) {
|
||||||
@@ -106,6 +107,7 @@ Function::Function(Symbol *s, Stmt *c) {
|
|||||||
code->Print(0);
|
code->Print(0);
|
||||||
printf("---------------------\n");
|
printf("---------------------\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (code != NULL) {
|
if (code != NULL) {
|
||||||
code = Optimize(code);
|
code = Optimize(code);
|
||||||
@@ -641,7 +643,6 @@ Function::IsPolyFunction() const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
std::vector<Function *> *
|
std::vector<Function *> *
|
||||||
Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
|
Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
|
||||||
Assert(symbolTable != NULL);
|
Assert(symbolTable != NULL);
|
||||||
@@ -659,30 +660,57 @@ Function::ExpandPolyArguments(SymbolTable *symbolTable) const {
|
|||||||
}
|
}
|
||||||
const FunctionType *ft = CastType<FunctionType>(versions[i]->type);
|
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);
|
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++) {
|
for (int j=0; j<ft->GetNumParameters(); j++) {
|
||||||
if (func->GetParameterType(j)->IsPolymorphicType()) {
|
if (func->GetParameterType(j)->IsPolymorphicType()) {
|
||||||
const PolyType *from = CastType<PolyType>(
|
const PolyType *from = CastType<PolyType>(
|
||||||
func->GetParameterType(j)->GetBaseType());
|
func->GetParameterType(j)->GetBaseType());
|
||||||
|
|
||||||
ncode = (Stmt*)TranslatePoly(ncode, from,
|
f->code = (Stmt*)TranslatePoly(f->code, from,
|
||||||
ft->GetParameterType(j)->GetBaseType());
|
ft->GetParameterType(j)->GetBaseType());
|
||||||
if (g->debugPrint) {
|
if (g->debugPrint) {
|
||||||
printf("%s after replacing %s with %s:\n\n",
|
printf("%s after replacing %s with %s:\n\n",
|
||||||
sym->name.c_str(), from->GetString().c_str(),
|
sym->name.c_str(), from->GetString().c_str(),
|
||||||
ft->GetParameterType(j)->GetBaseType()->GetString().c_str());
|
ft->GetParameterType(j)->GetBaseType()->GetString().c_str());
|
||||||
|
|
||||||
ncode->Print(0);
|
f->code->Print(0);
|
||||||
|
|
||||||
printf("------------------------------------------\n\n");
|
printf("------------------------------------------\n\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Symbol *s = symbolTable->LookupFunction(versions[i]->name.c_str(), ft);
|
// we didn't typecheck before, now we can
|
||||||
|
f->code = TypeCheck(f->code);
|
||||||
|
|
||||||
expanded->push_back(new Function(s, ncode));
|
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;
|
return expanded;
|
||||||
|
|||||||
2
func.h
2
func.h
@@ -44,7 +44,7 @@
|
|||||||
|
|
||||||
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;
|
||||||
|
|||||||
9
stmt.cpp
9
stmt.cpp
@@ -559,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.
|
||||||
@@ -577,9 +578,15 @@ DeclStmt::TypeCheck() {
|
|||||||
Stmt *
|
Stmt *
|
||||||
DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) {
|
DeclStmt::ReplacePolyType(const PolyType *from, const Type *to) {
|
||||||
for (size_t i = 0; i < vars.size(); i++) {
|
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;
|
Symbol *s = vars[i].sym;
|
||||||
if (Type::EqualForReplacement(s->type->GetBaseType(), from)) {
|
if (Type::EqualForReplacement(s->type->GetBaseType(), from)) {
|
||||||
s->type = PolyType::ReplaceType(s->type, to);
|
s->type = PolyType::ReplaceType(s->type, to);
|
||||||
|
|
||||||
|
// this typecast *should* be valid after typechecking
|
||||||
|
vars[i].init = TypeConvertExpr(vars[i].init, s->type,
|
||||||
|
"initializer");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
6
sym.cpp
6
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..
|
||||||
|
if (issueScopeWarning) {
|
||||||
Warning(symbol->pos,
|
Warning(symbol->pos,
|
||||||
"Symbol \"%s\" shadows symbol declared in outer scope.",
|
"Symbol \"%s\" shadows symbol declared in outer scope.",
|
||||||
symbol->name.c_str());
|
symbol->name.c_str());
|
||||||
|
}
|
||||||
(*variables.back())[symbol->name] = symbol;
|
(*variables.back())[symbol->name] = symbol;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
2
sym.h
2
sym.h
@@ -141,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,
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
CXX=g++
|
CXX=g++
|
||||||
CXXFLAGS=-std=c++11
|
CXXFLAGS=-std=c++11 -O2
|
||||||
|
|
||||||
ISPC=../ispc
|
ISPC=../ispc
|
||||||
ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64
|
ISPCFLAGS=--target=sse4-x2 -O2 --arch=x86-64
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
type.cpp
2
type.cpp
@@ -721,9 +721,11 @@ PolyType::ReplaceType(const Type *from, const Type *to) {
|
|||||||
if (from->IsVaryingType())
|
if (from->IsVaryingType())
|
||||||
t = t->GetAsVaryingType();
|
t = t->GetAsVaryingType();
|
||||||
|
|
||||||
|
if (g->debugPrint) {
|
||||||
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
|
fprintf(stderr, "Replacing type \"%s\" with \"%s\"\n",
|
||||||
from->GetString().c_str(),
|
from->GetString().c_str(),
|
||||||
t->GetString().c_str());
|
t->GetString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user