//===--- CGStmt.cpp - Emit LLVM Code from Statements ----------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This contains code to emit Stmt nodes as LLVM code.
//
//===----------------------------------------------------------------------===//
#include "CGDebugInfo.h"
#include "CodeGenModule.h"
#include "CodeGenFunction.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/InlineAsm.h"
#include "llvm/ADT/StringExtras.h"
using namespace clang;
using namespace CodeGen;
//===----------------------------------------------------------------------===//
// Statement Emission
//===----------------------------------------------------------------------===//
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
// Generate stoppoints if we are emitting debug info.
// Beginning of a Compound Statement (e.g. an opening '{') does not produce
// executable code. So do not generate a stoppoint for that.
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI && S->getStmtClass() != Stmt::CompoundStmtClass) {
DI->setLocation(S->getLocStart());
DI->EmitStopPoint(CurFn, Builder);
}
switch (S->getStmtClass()) {
default:
// Must be an expression in a stmt context. Emit the value (to get
// side-effects) and ignore the result.
if (const Expr *E = dyn_cast<Expr>(S)) {
if (!hasAggregateLLVMType(E->getType()))
EmitScalarExpr(E);
else if (E->getType()->isAnyComplexType())
EmitComplexExpr(E);
else
EmitAggExpr(E, 0, false);
} else {
ErrorUnsupported(S, "statement");
}
break;
case Stmt::NullStmtClass: break;
case Stmt::CompoundStmtClass: EmitCompoundStmt(cast<CompoundStmt>(*S)); break;
case Stmt::LabelStmtClass: EmitLabelStmt(cast<LabelStmt>(*S)); break;
case Stmt::GotoStmtClass: EmitGotoStmt(cast<GotoStmt>(*S)); break;
case Stmt::IndirectGotoStmtClass:
EmitIndirectGotoStmt(cast<IndirectGotoStmt>(*S)); break;
case Stmt::IfStmtClass: EmitIfStmt(cast<IfStmt>(*S)); break;
case Stmt::WhileStmtClass: EmitWhileStmt(cast<WhileStmt>(*S)); break;
case Stmt::DoStmtClass: EmitDoStmt(cast<DoStmt>(*S)); break;
case Stmt::ForStmtClass: EmitForStmt(cast<ForStmt>(*S)); break;
case Stmt::ReturnStmtClass: EmitReturnStmt(cast<ReturnStmt>(*S)); break;
case Stmt::DeclStmtClass: EmitDeclStmt(cast<DeclStmt>(*S)); break;
case Stmt::BreakStmtClass:
// FIXME: Implement break in @try or @catch blocks.
if (!ObjCEHStack.empty()) {
CGM.ErrorUnsupported(S, "continue inside an Obj-C exception block");
return;
}
EmitBreakStmt();
break;
case Stmt::ContinueStmtClass:
// FIXME: Implement continue in @try or @catch blocks.
if (!ObjCEHStack.empty()) {
CGM.ErrorUnsupported(S, "continue inside an Obj-C exception block");
return;
}
EmitContinueStmt();
break;
case Stmt::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*S)); break;
case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
case Stmt::AsmStmtClass: EmitAsmStmt(cast<AsmStmt>(*S)); break;
case Stmt::ObjCAtTryStmtClass:
EmitObjCAtTryStmt(cast<ObjCAtTryStmt>(*S));
break;
case Stmt::ObjCAtCatchStmtClass:
assert(0 && "@catch statements should be handled by EmitObjCAtTryStmt");
break;
case Stmt::ObjCAtFinallyStmtClass:
assert(0 && "@finally statements should be handled by EmitObjCAtTryStmt");
break;
case Stmt::ObjCAtThrowStmtClass:
EmitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(*S));
break;
case Stmt::ObjCAtSynchronizedStmtClass:
ErrorUnsupported(S, "@synchronized statement");
break;
case Stmt::ObjCForCollectionStmtClass:
EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
break;
}
}
/// EmitCompoundStmt - Emit a compound statement {..} node. If GetLast is true,
/// this captures the expression result of the last sub-statement and returns it
/// (for use by the statement expression extension).
RValue CodeGenFunction::EmitCompoundStmt(const CompoundStmt &S, bool GetLast,
llvm::Value *AggLoc, bool isAggVol) {
// FIXME: handle vla's etc.
CGDebugInfo *DI = CGM.getDebugInfo();
if (DI) {
DI->setLocation(S.getLBracLoc());
DI->EmitRegionStart(CurFn, Builder);
}
for (CompoundStmt::const_body_iterator I =<