Distinguish between 'regular' foreach and foreach_unique in FunctionEmitContext
We need to do this since it's illegal to have nested foreach statements, but nested foreach_unique, or foreach_unique inside foreach, etc., are all fine.
This commit is contained in:
38
ctx.cpp
38
ctx.cpp
@@ -68,7 +68,8 @@ struct CFInfo {
|
|||||||
llvm::Value *savedContinueLanesPtr,
|
llvm::Value *savedContinueLanesPtr,
|
||||||
llvm::Value *savedMask, llvm::Value *savedLoopMask);
|
llvm::Value *savedMask, llvm::Value *savedLoopMask);
|
||||||
|
|
||||||
static CFInfo *GetForeach(llvm::BasicBlock *breakTarget,
|
static CFInfo *GetForeach(FunctionEmitContext::ForeachType ft,
|
||||||
|
llvm::BasicBlock *breakTarget,
|
||||||
llvm::BasicBlock *continueTarget,
|
llvm::BasicBlock *continueTarget,
|
||||||
llvm::Value *savedBreakLanesPtr,
|
llvm::Value *savedBreakLanesPtr,
|
||||||
llvm::Value *savedContinueLanesPtr,
|
llvm::Value *savedContinueLanesPtr,
|
||||||
@@ -87,12 +88,13 @@ struct CFInfo {
|
|||||||
|
|
||||||
bool IsIf() { return type == If; }
|
bool IsIf() { return type == If; }
|
||||||
bool IsLoop() { return type == Loop; }
|
bool IsLoop() { return type == Loop; }
|
||||||
bool IsForeach() { return type == Foreach; }
|
bool IsForeach() { return (type == ForeachRegular ||
|
||||||
|
type == ForeachUnique); }
|
||||||
bool IsSwitch() { return type == Switch; }
|
bool IsSwitch() { return type == Switch; }
|
||||||
bool IsVarying() { return !isUniform; }
|
bool IsVarying() { return !isUniform; }
|
||||||
bool IsUniform() { return isUniform; }
|
bool IsUniform() { return isUniform; }
|
||||||
|
|
||||||
enum CFType { If, Loop, Foreach, Switch };
|
enum CFType { If, Loop, ForeachRegular, ForeachUnique, Switch };
|
||||||
CFType type;
|
CFType type;
|
||||||
bool isUniform;
|
bool isUniform;
|
||||||
llvm::BasicBlock *savedBreakTarget, *savedContinueTarget;
|
llvm::BasicBlock *savedBreakTarget, *savedContinueTarget;
|
||||||
@@ -141,7 +143,7 @@ private:
|
|||||||
CFInfo(CFType t, llvm::BasicBlock *bt, llvm::BasicBlock *ct,
|
CFInfo(CFType t, llvm::BasicBlock *bt, llvm::BasicBlock *ct,
|
||||||
llvm::Value *sb, llvm::Value *sc, llvm::Value *sm,
|
llvm::Value *sb, llvm::Value *sc, llvm::Value *sm,
|
||||||
llvm::Value *lm) {
|
llvm::Value *lm) {
|
||||||
Assert(t == Foreach);
|
Assert(t == ForeachRegular || t == ForeachUnique);
|
||||||
type = t;
|
type = t;
|
||||||
isUniform = false;
|
isUniform = false;
|
||||||
savedBreakTarget = bt;
|
savedBreakTarget = bt;
|
||||||
@@ -177,12 +179,25 @@ CFInfo::GetLoop(bool isUniform, llvm::BasicBlock *breakTarget,
|
|||||||
|
|
||||||
|
|
||||||
CFInfo *
|
CFInfo *
|
||||||
CFInfo::GetForeach(llvm::BasicBlock *breakTarget,
|
CFInfo::GetForeach(FunctionEmitContext::ForeachType ft,
|
||||||
|
llvm::BasicBlock *breakTarget,
|
||||||
llvm::BasicBlock *continueTarget,
|
llvm::BasicBlock *continueTarget,
|
||||||
llvm::Value *savedBreakLanesPtr,
|
llvm::Value *savedBreakLanesPtr,
|
||||||
llvm::Value *savedContinueLanesPtr,
|
llvm::Value *savedContinueLanesPtr,
|
||||||
llvm::Value *savedMask, llvm::Value *savedForeachMask) {
|
llvm::Value *savedMask, llvm::Value *savedForeachMask) {
|
||||||
return new CFInfo(Foreach, breakTarget, continueTarget,
|
CFType cfType;
|
||||||
|
switch (ft) {
|
||||||
|
case FunctionEmitContext::FOREACH_REGULAR:
|
||||||
|
cfType = ForeachRegular;
|
||||||
|
break;
|
||||||
|
case FunctionEmitContext::FOREACH_UNIQUE:
|
||||||
|
cfType = ForeachUnique;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FATAL("Unhandled foreach type");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CFInfo(cfType, breakTarget, continueTarget,
|
||||||
savedBreakLanesPtr, savedContinueLanesPtr,
|
savedBreakLanesPtr, savedContinueLanesPtr,
|
||||||
savedMask, savedForeachMask);
|
savedMask, savedForeachMask);
|
||||||
}
|
}
|
||||||
@@ -583,11 +598,13 @@ FunctionEmitContext::EndLoop() {
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FunctionEmitContext::StartForeach() {
|
FunctionEmitContext::StartForeach(ForeachType ft) {
|
||||||
// Issue an error if we're in a nested foreach...
|
// Issue an error if we're in a nested foreach...
|
||||||
|
if (ft == FOREACH_REGULAR) {
|
||||||
for (int i = 0; i < (int)controlFlowInfo.size(); ++i) {
|
for (int i = 0; i < (int)controlFlowInfo.size(); ++i) {
|
||||||
if (controlFlowInfo[i]->type == CFInfo::Foreach) {
|
if (controlFlowInfo[i]->type == CFInfo::ForeachRegular) {
|
||||||
Error(currentPos, "Nested \"foreach\" statements are currently illegal.");
|
Error(currentPos, "Nested \"foreach\" statements are currently "
|
||||||
|
"illegal.");
|
||||||
break;
|
break;
|
||||||
// Don't return here, however, and in turn allow the caller to
|
// Don't return here, however, and in turn allow the caller to
|
||||||
// do the rest of its codegen and then call EndForeach()
|
// do the rest of its codegen and then call EndForeach()
|
||||||
@@ -595,11 +612,12 @@ FunctionEmitContext::StartForeach() {
|
|||||||
// any other errors inside the body of the foreach loop...
|
// any other errors inside the body of the foreach loop...
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Store the current values of various loop-related state so that we
|
// Store the current values of various loop-related state so that we
|
||||||
// can restore it when we exit this loop.
|
// can restore it when we exit this loop.
|
||||||
llvm::Value *oldMask = GetInternalMask();
|
llvm::Value *oldMask = GetInternalMask();
|
||||||
controlFlowInfo.push_back(CFInfo::GetForeach(breakTarget, continueTarget,
|
controlFlowInfo.push_back(CFInfo::GetForeach(ft, breakTarget, continueTarget,
|
||||||
breakLanesPtr, continueLanesPtr,
|
breakLanesPtr, continueLanesPtr,
|
||||||
oldMask, loopMask));
|
oldMask, loopMask));
|
||||||
breakLanesPtr = NULL;
|
breakLanesPtr = NULL;
|
||||||
|
|||||||
7
ctx.h
7
ctx.h
@@ -160,9 +160,10 @@ public:
|
|||||||
finished. */
|
finished. */
|
||||||
void EndLoop();
|
void EndLoop();
|
||||||
|
|
||||||
/** Indicates that code generation for a 'foreach' or 'foreach_tiled'
|
/** Indicates that code generation for a 'foreach', 'foreach_tiled', or
|
||||||
loop is about to start. */
|
'foreach_unique' loop is about to start. */
|
||||||
void StartForeach();
|
enum ForeachType { FOREACH_REGULAR, FOREACH_UNIQUE };
|
||||||
|
void StartForeach(ForeachType ft);
|
||||||
void EndForeach();
|
void EndForeach();
|
||||||
|
|
||||||
/** Emit code for a 'break' statement in a loop. If doCoherenceCheck
|
/** Emit code for a 'break' statement in a loop. If doCoherenceCheck
|
||||||
|
|||||||
8
stmt.cpp
8
stmt.cpp
@@ -1458,7 +1458,7 @@ ForeachStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
ctx->StoreInst(LLVMMaskAllOn, extrasMaskPtrs[i]);
|
ctx->StoreInst(LLVMMaskAllOn, extrasMaskPtrs[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx->StartForeach();
|
ctx->StartForeach(FunctionEmitContext::FOREACH_REGULAR);
|
||||||
|
|
||||||
// On to the outermost loop's test
|
// On to the outermost loop's test
|
||||||
ctx->BranchInst(bbTest[0]);
|
ctx->BranchInst(bbTest[0]);
|
||||||
@@ -1970,10 +1970,8 @@ ForeachUniqueStmt::EmitCode(FunctionEmitContext *ctx) const {
|
|||||||
llvm::Value *movmsk = ctx->LaneMask(oldFullMask);
|
llvm::Value *movmsk = ctx->LaneMask(oldFullMask);
|
||||||
ctx->StoreInst(movmsk, maskBitsPtr);
|
ctx->StoreInst(movmsk, maskBitsPtr);
|
||||||
|
|
||||||
// Officially start the loop; as far as the FunctionEmitContext is
|
// Officially start the loop.
|
||||||
// concerned, this can be handled the same way as a regular foreach
|
ctx->StartForeach(FunctionEmitContext::FOREACH_UNIQUE);
|
||||||
// loop (continue allowed but not break and return, etc.)
|
|
||||||
ctx->StartForeach();
|
|
||||||
ctx->SetContinueTarget(bbCheckForMore);
|
ctx->SetContinueTarget(bbCheckForMore);
|
||||||
|
|
||||||
// Evaluate the varying expression we're iterating over just once.
|
// Evaluate the varying expression we're iterating over just once.
|
||||||
|
|||||||
Reference in New Issue
Block a user