Add initial support for 'goto' statements.

ispc now supports goto, but only under uniform control flow--i.e.
it must be possible for the compiler to statically determine that
all program instances will follow the goto.  An error is issued at
compile time if a goto is used when this is not the case.
This commit is contained in:
Matt Pharr
2012-01-05 12:20:44 -08:00
parent 48e9d4af39
commit 78c6d3c02f
20 changed files with 408 additions and 15 deletions

45
ctx.cpp
View File

@@ -77,7 +77,7 @@ struct CFInfo {
bool IsIf() { return type == If; }
bool IsLoop() { return type == Loop; }
bool IsForeach() { return type == Foreach; }
bool IsVaryingType() { return !isUniform; }
bool IsVarying() { return !isUniform; }
bool IsUniform() { return isUniform; }
enum CFType { If, Loop, Foreach };
@@ -157,9 +157,10 @@ CFInfo::GetForeach(llvm::BasicBlock *breakTarget,
///////////////////////////////////////////////////////////////////////////
FunctionEmitContext::FunctionEmitContext(Function *func, Symbol *funSym,
llvm::Function *llvmFunction,
llvm::Function *lf,
SourcePos firstStmtPos) {
function = func;
llvmFunction = lf;
/* Create a new basic block to store all of the allocas */
allocaBlock = llvm::BasicBlock::Create(*g->ctx, "allocas", llvmFunction, 0);
@@ -762,7 +763,7 @@ int
FunctionEmitContext::VaryingCFDepth() const {
int sum = 0;
for (unsigned int i = 0; i < controlFlowInfo.size(); ++i)
if (controlFlowInfo[i]->IsVaryingType())
if (controlFlowInfo[i]->IsVarying())
++sum;
return sum;
}
@@ -777,6 +778,41 @@ FunctionEmitContext::InForeachLoop() const {
}
bool
FunctionEmitContext::initLabelBBlocks(ASTNode *node, void *data) {
LabeledStmt *ls = dynamic_cast<LabeledStmt *>(node);
if (ls == NULL)
return true;
FunctionEmitContext *ctx = (FunctionEmitContext *)data;
if (ctx->labelMap.find(ls->name) != ctx->labelMap.end())
Error(ls->pos, "Multiple labels named \"%s\" in function.",
ls->name.c_str());
else {
llvm::BasicBlock *bb = ctx->CreateBasicBlock(ls->name.c_str());
ctx->labelMap[ls->name] = bb;
}
return true;
}
void
FunctionEmitContext::InitializeLabelMap(Stmt *code) {
labelMap.erase(labelMap.begin(), labelMap.end());
WalkAST(code, initLabelBBlocks, NULL, this);
}
llvm::BasicBlock *
FunctionEmitContext::GetLabeledBasicBlock(const std::string &label) {
if (labelMap.find(label) != labelMap.end())
return labelMap[label];
else
return NULL;
}
void
FunctionEmitContext::CurrentLanesReturned(Expr *expr, bool doCoherenceCheck) {
const Type *returnType = function->GetReturnType();
@@ -920,8 +956,7 @@ FunctionEmitContext::GetStringPtr(const std::string &str) {
llvm::BasicBlock *
FunctionEmitContext::CreateBasicBlock(const char *name) {
llvm::Function *function = bblock->getParent();
return llvm::BasicBlock::Create(*g->ctx, name, function);
return llvm::BasicBlock::Create(*g->ctx, name, llvmFunction);
}