|
@@ -262,6 +262,8 @@ void SPIRVEmitter::doStmt(const Stmt *stmt,
|
|
doBreakStmt(breakStmt);
|
|
doBreakStmt(breakStmt);
|
|
} else if (const auto *theDoStmt = dyn_cast<DoStmt>(stmt)) {
|
|
} else if (const auto *theDoStmt = dyn_cast<DoStmt>(stmt)) {
|
|
doDoStmt(theDoStmt, attrs);
|
|
doDoStmt(theDoStmt, attrs);
|
|
|
|
+ } else if (const auto *discardStmt = dyn_cast<DiscardStmt>(stmt)) {
|
|
|
|
+ doDiscardStmt(discardStmt);
|
|
} else if (const auto *continueStmt = dyn_cast<ContinueStmt>(stmt)) {
|
|
} else if (const auto *continueStmt = dyn_cast<ContinueStmt>(stmt)) {
|
|
doContinueStmt(continueStmt);
|
|
doContinueStmt(continueStmt);
|
|
} else if (const auto *whileStmt = dyn_cast<WhileStmt>(stmt)) {
|
|
} else if (const auto *whileStmt = dyn_cast<WhileStmt>(stmt)) {
|
|
@@ -383,6 +385,11 @@ uint32_t SPIRVEmitter::castToType(uint32_t value, QualType fromType,
|
|
}
|
|
}
|
|
|
|
|
|
void SPIRVEmitter::doFunctionDecl(const FunctionDecl *decl) {
|
|
void SPIRVEmitter::doFunctionDecl(const FunctionDecl *decl) {
|
|
|
|
+ // We are about to start translation for a new function. Clear the break stack
|
|
|
|
+ // and the continue stack.
|
|
|
|
+ breakStack = std::stack<uint32_t>();
|
|
|
|
+ continueStack = std::stack<uint32_t>();
|
|
|
|
+
|
|
curFunction = decl;
|
|
curFunction = decl;
|
|
|
|
|
|
const llvm::StringRef funcName = decl->getName();
|
|
const llvm::StringRef funcName = decl->getName();
|
|
@@ -538,6 +545,16 @@ spv::LoopControlMask SPIRVEmitter::translateLoopAttribute(const Attr &attr) {
|
|
return spv::LoopControlMask::MaskNone;
|
|
return spv::LoopControlMask::MaskNone;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void SPIRVEmitter::doDiscardStmt(const DiscardStmt *discardStmt) {
|
|
|
|
+ assert(!theBuilder.isCurrentBasicBlockTerminated());
|
|
|
|
+ theBuilder.createKill();
|
|
|
|
+ if (!isLastStmtBeforeControlFlowBranching(astContext, discardStmt)) {
|
|
|
|
+ const uint32_t unreachableBB =
|
|
|
|
+ theBuilder.createBasicBlock("unreachable", /*isReachable*/ false);
|
|
|
|
+ theBuilder.setInsertPoint(unreachableBB);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
void SPIRVEmitter::doDoStmt(const DoStmt *theDoStmt,
|
|
void SPIRVEmitter::doDoStmt(const DoStmt *theDoStmt,
|
|
llvm::ArrayRef<const Attr *> attrs) {
|
|
llvm::ArrayRef<const Attr *> attrs) {
|
|
// do-while loops are composed of:
|
|
// do-while loops are composed of:
|
|
@@ -934,6 +951,17 @@ void SPIRVEmitter::doIfStmt(const IfStmt *ifStmt) {
|
|
}
|
|
}
|
|
|
|
|
|
void SPIRVEmitter::doReturnStmt(const ReturnStmt *stmt) {
|
|
void SPIRVEmitter::doReturnStmt(const ReturnStmt *stmt) {
|
|
|
|
+ processReturnStmt(stmt);
|
|
|
|
+
|
|
|
|
+ // Handle early returns
|
|
|
|
+ if (!isLastStmtBeforeControlFlowBranching(astContext, stmt)) {
|
|
|
|
+ const uint32_t unreachableBB =
|
|
|
|
+ theBuilder.createBasicBlock("unreachable", /*isReachable*/ false);
|
|
|
|
+ theBuilder.setInsertPoint(unreachableBB);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void SPIRVEmitter::processReturnStmt(const ReturnStmt *stmt) {
|
|
// For normal functions, just return in the normal way.
|
|
// For normal functions, just return in the normal way.
|
|
if (curFunction->getName() != entryFunctionName) {
|
|
if (curFunction->getName() != entryFunctionName) {
|
|
theBuilder.createReturnValue(doExpr(stmt->getRetValue()));
|
|
theBuilder.createReturnValue(doExpr(stmt->getRetValue()));
|
|
@@ -958,6 +986,12 @@ void SPIRVEmitter::doReturnStmt(const ReturnStmt *stmt) {
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ // RetValue is nullptr when "return;" is used for a void function.
|
|
|
|
+ if (!stmt->getRetValue()) {
|
|
|
|
+ theBuilder.createReturn();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
QualType retType = stmt->getRetValue()->getType();
|
|
QualType retType = stmt->getRetValue()->getType();
|
|
|
|
|
|
if (const auto *structType = retType->getAsStructureType()) {
|
|
if (const auto *structType = retType->getAsStructureType()) {
|