Newer
Older
//===--- 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/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
Anders Carlsson
committed
#include "llvm/InlineAsm.h"
#include "llvm/Intrinsics.h"
using namespace clang;
using namespace CodeGen;
//===----------------------------------------------------------------------===//
// Statement Emission
//===----------------------------------------------------------------------===//
void CodeGenFunction::EmitStopPoint(const Stmt *S) {
if (CGDebugInfo *DI = getDebugInfo()) {
DI->setLocation(S->getLocStart());
DI->EmitStopPoint(CurFn, Builder);
}
}
void CodeGenFunction::EmitStmt(const Stmt *S) {
assert(S && "Null statement?");
// Check if we can handle this without bothering to generate an
// insert point or debug info.
if (EmitSimpleStmt(S))
return;
// If we happen to be at an unreachable point just create a dummy
// basic block to hold the code. We could change parts of irgen to
// simply not generate this code, but this situation is rare and
// probably not worth the effort.
// FIXME: Verify previous performance/effort claim.
EnsureInsertPoint();
// Generate a stoppoint if we are emitting debug info.
EmitStopPoint(S);
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);
Chris Lattner
committed
else if (E->getType()->isAnyComplexType())
EmitComplexExpr(E);
else
EmitAggExpr(E, 0, false);
ErrorUnsupported(S, "statement");
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::SwitchStmtClass: EmitSwitchStmt(cast<SwitchStmt>(*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:
EmitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(*S));
case Stmt::ObjCForCollectionStmtClass:
EmitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(*S));
bool CodeGenFunction::EmitSimpleStmt(const Stmt *S) {
switch (S->getStmtClass()) {
default: return false;
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::BreakStmtClass: EmitBreakStmt(cast<BreakStmt>(*S)); break;
case Stmt::ContinueStmtClass: EmitContinueStmt(cast<ContinueStmt>(*S)); break;
case Stmt::DefaultStmtClass: EmitDefaultStmt(cast<DefaultStmt>(*S)); break;
case Stmt::CaseStmtClass: EmitCaseStmt(cast<CaseStmt>(*S)); break;
}
return true;
}
/// 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) {
Anders Carlsson
committed
CGDebugInfo *DI = getDebugInfo();
DI->setLocation(S.getLBracLoc());
DI->EmitRegionStart(CurFn, Builder);
}
Anders Carlsson
committed
// Keep track of the current cleanup stack depth.
size_t CleanupStackDepth = CleanupEntries.size();
bool OldDidCallStackSave = DidCallStackSave;
for (CompoundStmt::const_body_iterator I = S.body_begin(),
E = S.body_end()-GetLast; I != E; ++I)
EnsureInsertPoint();
DI->setLocation(S.getRBracLoc());
DI->EmitRegionEnd(CurFn, Builder);
}
Anders Carlsson
committed
RValue RV;
if (!GetLast)
RV = RValue::get(0);
else {
// We have to special case labels here. They are statements, but when put
// at the end of a statement expression, they yield the value of their
// subexpression. Handle this by walking through all labels we encounter,
// emitting them before we evaluate the subexpr.
const Stmt *LastStmt = S.body_back();
while (const LabelStmt *LS = dyn_cast<LabelStmt>(LastStmt)) {
EmitLabel(*LS);
LastStmt = LS->getSubStmt();
}
Anders Carlsson
committed
EnsureInsertPoint();
RV = EmitAnyExpr(cast<Expr>(LastStmt), AggLoc);
DidCallStackSave = OldDidCallStackSave;
Anders Carlsson
committed
EmitCleanupBlocks(CleanupStackDepth);
Anders Carlsson
committed
return RV;
void CodeGenFunction::EmitBlock(llvm::BasicBlock *BB, bool IsFinished) {
// Fall out of the current block (if necessary).
EmitBranch(BB);
if (IsFinished && BB->use_empty()) {
delete BB;
return;
}
Anders Carlsson
committed
// If necessary, associate the block with the cleanup stack size.
if (!CleanupEntries.empty()) {
Anders Carlsson
committed
// Check if the basic block has already been inserted.
BlockScopeMap::iterator I = BlockScopes.find(BB);
if (I != BlockScopes.end()) {
assert(I->second == CleanupEntries.size() - 1);
} else {
BlockScopes[BB] = CleanupEntries.size() - 1;
CleanupEntries.back().Blocks.push_back(BB);
}
Anders Carlsson
committed
}
CurFn->getBasicBlockList().push_back(BB);
Builder.SetInsertPoint(BB);
}
void CodeGenFunction::EmitBranch(llvm::BasicBlock *Target) {
// Emit a branch from the current block to the target one if this
// was a real block. If this was just a fall-through block after a
// terminator, don't emit it.
llvm::BasicBlock *CurBB = Builder.GetInsertBlock();
if (!CurBB || CurBB->getTerminator()) {
// If there is no insert point or the previous block is already
// terminated, don't touch it.
} else {
// Otherwise, create a fall-through branch.
Builder.ClearInsertionPoint();
void CodeGenFunction::EmitLabel(const LabelStmt &S) {
EmitBlock(getBasicBlockForLabel(&S));
}
void CodeGenFunction::EmitLabelStmt(const LabelStmt &S) {
EmitLabel(S);
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitGotoStmt(const GotoStmt &S) {
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
Anders Carlsson
committed
EmitBranchThroughCleanup(getBasicBlockForLabel(S.getLabel()));
void CodeGenFunction::EmitIndirectGotoStmt(const IndirectGotoStmt &S) {
// Emit initial switch which will be patched up later by
// EmitIndirectSwitches(). We need a default dest, so we use the
// current BB, but this is overwritten.
llvm::Value *V = Builder.CreatePtrToInt(EmitScalarExpr(S.getTarget()),
llvm::Type::Int32Ty,
"addr");
llvm::SwitchInst *I = Builder.CreateSwitch(V, Builder.GetInsertBlock());
IndirectSwitches.push_back(I);
// Clear the insertion point to indicate we are in unreachable code.
Builder.ClearInsertionPoint();
void CodeGenFunction::EmitIfStmt(const IfStmt &S) {
// C99 6.8.4.1: The first substatement is executed if the expression compares
// unequal to 0. The condition must be a scalar type.
// If the condition constant folds and can be elided, try to avoid emitting
// the condition and the dead arm of the if/else.
if (int Cond = ConstantFoldsToSimpleInteger(S.getCond())) {
// Figure out which block (then or else) is executed.
const Stmt *Executed = S.getThen(), *Skipped = S.getElse();
if (Cond == -1) // Condition false?
std::swap(Executed, Skipped);
// If the skipped block has no labels in it, just emit the executed block.
// This avoids emitting dead code and simplifies the CFG substantially.
if (!ContainsLabel(Skipped)) {
if (Executed)
EmitStmt(Executed);
return;
}
}
// Otherwise, the condition did not fold, or we couldn't elide it. Just emit
// the conditional branch.
llvm::BasicBlock *ThenBlock = createBasicBlock("if.then");
llvm::BasicBlock *ContBlock = createBasicBlock("if.end");
llvm::BasicBlock *ElseBlock = ContBlock;
ElseBlock = createBasicBlock("if.else");
EmitBranchOnBoolExpr(S.getCond(), ThenBlock, ElseBlock);
// Emit the 'then' code.
EmitBlock(ThenBlock);
EmitStmt(S.getThen());
// Emit the 'else' code if present.
if (const Stmt *Else = S.getElse()) {
EmitBlock(ElseBlock);
EmitStmt(Else);
}
// Emit the continuation block for code after the if.
EmitBlock(ContBlock, true);
void CodeGenFunction::EmitWhileStmt(const WhileStmt &S) {
// Emit the header for the loop, insert it, which will create an uncond br to
// it.
llvm::BasicBlock *LoopHeader = createBasicBlock("while.cond");
EmitBlock(LoopHeader);
// Create an exit block for when the condition fails, create a block for the
// body of the loop.
llvm::BasicBlock *ExitBlock = createBasicBlock("while.end");
llvm::BasicBlock *LoopBody = createBasicBlock("while.body");
// Store the blocks to use for break and continue.
Anders Carlsson
committed
BreakContinueStack.push_back(BreakContinue(ExitBlock, LoopHeader));
// Evaluate the conditional in the while header. C99 6.8.5.1: The
// evaluation of the controlling expression takes place before each
// execution of the loop body.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
// while(1) is common, avoid extra exit blocks. Be sure
// to correctly handle break/continue though.
bool EmitBoolCondBranch = true;
if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
if (C->isOne())
EmitBoolCondBranch = false;
// As long as the condition is true, go to the loop body.
if (EmitBoolCondBranch)
Builder.CreateCondBr(BoolCondVal, LoopBody, ExitBlock);
// Emit the loop body.
EmitBlock(LoopBody);
EmitStmt(S.getBody());
Anders Carlsson
committed
BreakContinueStack.pop_back();
// Cycle to the condition.
// Emit the exit block.
EmitBlock(ExitBlock, true);
// If LoopHeader is a simple forwarding block then eliminate it.
if (!EmitBoolCondBranch
&& &LoopHeader->front() == LoopHeader->getTerminator()) {
LoopHeader->replaceAllUsesWith(LoopBody);
LoopHeader->getTerminator()->eraseFromParent();
LoopHeader->eraseFromParent();
}
}
void CodeGenFunction::EmitDoStmt(const DoStmt &S) {
// Emit the body for the loop, insert it, which will create an uncond br to
// it.
llvm::BasicBlock *LoopBody = createBasicBlock("do.body");
llvm::BasicBlock *AfterDo = createBasicBlock("do.end");
EmitBlock(LoopBody);
llvm::BasicBlock *DoCond = createBasicBlock("do.cond");
// Store the blocks to use for break and continue.
Anders Carlsson
committed
BreakContinueStack.push_back(BreakContinue(AfterDo, DoCond));
// Emit the body of the loop into the block.
EmitStmt(S.getBody());
Anders Carlsson
committed
BreakContinueStack.pop_back();
EmitBlock(DoCond);
// C99 6.8.5.2: "The evaluation of the controlling expression takes place
// after each execution of the loop body."
// Evaluate the conditional in the while header.
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
llvm::Value *BoolCondVal = EvaluateExprAsBool(S.getCond());
// "do {} while (0)" is common in macros, avoid extra blocks. Be sure
// to correctly handle break/continue though.
bool EmitBoolCondBranch = true;
if (llvm::ConstantInt *C = dyn_cast<llvm::ConstantInt>(BoolCondVal))
if (C->isZero())
EmitBoolCondBranch = false;
// As long as the condition is true, iterate the loop.
if (EmitBoolCondBranch)
Builder.CreateCondBr(BoolCondVal, LoopBody, AfterDo);
// Emit the exit block.
EmitBlock(AfterDo, true);
// If DoCond is a simple forwarding block then eliminate it.
if (!EmitBoolCondBranch && &DoCond->front() == DoCond->getTerminator()) {
DoCond->replaceAllUsesWith(AfterDo);
DoCond->getTerminator()->eraseFromParent();
DoCond->eraseFromParent();
}
}
void CodeGenFunction::EmitForStmt(const ForStmt &S) {
// FIXME: What do we do if the increment (f.e.) contains a stmt expression,
// which contains a continue/break?
// Evaluate the first part before the loop.
if (S.getInit())
EmitStmt(S.getInit());
// Start the loop with a block that tests the condition.
llvm::BasicBlock *CondBlock = createBasicBlock("for.cond");
llvm::BasicBlock *AfterFor = createBasicBlock("for.end");
EmitBlock(CondBlock);
// Evaluate the condition if present. If not, treat it as a
// non-zero-constant according to 6.8.5.3p2, aka, true.
if (S.getCond()) {
// As long as the condition is true, iterate the loop.
llvm::BasicBlock *ForBody = createBasicBlock("for.body");
// C99 6.8.5p2/p4: The first substatement is executed if the expression
// compares unequal to 0. The condition must be a scalar type.
EmitBranchOnBoolExpr(S.getCond(), ForBody, AfterFor);
EmitBlock(ForBody);
} else {
// Treat it as a non-zero constant. Don't even create a new block for the
// body, just fall into it.
}
// If the for loop doesn't have an increment we can just use the
// condition as the continue block.
llvm::BasicBlock *ContinueBlock;
if (S.getInc())
ContinueBlock = createBasicBlock("for.inc");
else
ContinueBlock = CondBlock;
// Store the blocks to use for break and continue.
Anders Carlsson
committed
BreakContinueStack.push_back(BreakContinue(AfterFor, ContinueBlock));
// If the condition is true, execute the body of the for stmt.
EmitStmt(S.getBody());
Anders Carlsson
committed
BreakContinueStack.pop_back();
// If there is an increment, emit it next.
Chris Lattner
committed
EmitStmt(S.getInc());
// Finally, branch back up to the condition for the next iteration.
// Emit the fall-through block.
EmitBlock(AfterFor, true);
}
void CodeGenFunction::EmitReturnOfRValue(RValue RV, QualType Ty) {
if (RV.isScalar()) {
Builder.CreateStore(RV.getScalarVal(), ReturnValue);
} else if (RV.isAggregate()) {
EmitAggregateCopy(ReturnValue, RV.getAggregateAddr(), Ty);
} else {
StoreComplexToAddr(RV.getComplexVal(), ReturnValue, false);
}
Anders Carlsson
committed
EmitBranchThroughCleanup(ReturnBlock);
/// EmitReturnStmt - Note that due to GCC extensions, this can have an operand
/// if the function returns void, or may be missing one if the function returns
/// non-void. Fun stuff :).
void CodeGenFunction::EmitReturnStmt(const ReturnStmt &S) {
// Emit the result value, even if unused, to evalute the side effects.
const Expr *RV = S.getRetValue();
// FIXME: Clean this up by using an LValue for ReturnTemp,
// EmitStoreThroughLValue, and EmitAnyExpr.
if (!ReturnValue) {
// Make sure not to return anything, but evaluate the expression
// for side effects.
if (RV)
EmitAnyExpr(RV);
} else if (RV == 0) {
// Do nothing (return value is left uninitialized)
} else if (!hasAggregateLLVMType(RV->getType())) {
Builder.CreateStore(EmitScalarExpr(RV), ReturnValue);
Chris Lattner
committed
} else if (RV->getType()->isAnyComplexType()) {
EmitComplexExprIntoAddr(RV, ReturnValue, false);
} else {
Anders Carlsson
committed
EmitBranchThroughCleanup(ReturnBlock);
void CodeGenFunction::EmitDeclStmt(const DeclStmt &S) {
Ted Kremenek
committed
for (DeclStmt::const_decl_iterator I = S.decl_begin(), E = S.decl_end();
I != E; ++I)
EmitDecl(**I);
void CodeGenFunction::EmitBreakStmt(const BreakStmt &S) {
assert(!BreakContinueStack.empty() && "break stmt not in a loop or switch!");
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
llvm::BasicBlock *Block = BreakContinueStack.back().BreakBlock;
Anders Carlsson
committed
EmitBranchThroughCleanup(Block);
void CodeGenFunction::EmitContinueStmt(const ContinueStmt &S) {
assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
// If this code is reachable then emit a stop point (if generating
// debug info). We have to do this ourselves because we are on the
// "simple" statement path.
if (HaveInsertPoint())
EmitStopPoint(&S);
llvm::BasicBlock *Block = BreakContinueStack.back().ContinueBlock;
Anders Carlsson
committed
EmitBranchThroughCleanup(Block);
/// EmitCaseStmtRange - If case statement range is not too big then
/// add multiple cases to switch instruction, one for each value within
/// the range. If range is too big then emit "if" condition check.
void CodeGenFunction::EmitCaseStmtRange(const CaseStmt &S) {
assert(S.getRHS() && "Expected RHS value in CaseStmt");
llvm::APSInt LHS = S.getLHS()->EvaluateAsInt(getContext());
llvm::APSInt RHS = S.getRHS()->EvaluateAsInt(getContext());
// Emit the code for this case. We do this first to make sure it is
// properly chained from our predecessor before generating the
// switch machinery to enter this block.
EmitBlock(createBasicBlock("sw.bb"));
llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
EmitStmt(S.getSubStmt());
// If range is empty, do nothing.
if (LHS.isSigned() ? RHS.slt(LHS) : RHS.ult(LHS))
return;
// FIXME: parameters such as this should not be hardcoded.
if (Range.ult(llvm::APInt(Range.getBitWidth(), 64))) {
// Range is small enough to add multiple switch instruction cases.
for (unsigned i = 0, e = Range.getZExtValue() + 1; i != e; ++i) {
SwitchInsn->addCase(llvm::ConstantInt::get(LHS), CaseDest);
LHS++;
}
// The range is too big. Emit "if" condition into a new block,
// making sure to save and restore the current insertion point.
llvm::BasicBlock *RestoreBB = Builder.GetInsertBlock();
// Push this test onto the chain of range checks (which terminates
// in the default basic block). The switch's default will be changed
// to the top of this chain after switch emission is complete.
llvm::BasicBlock *FalseDest = CaseRangeBlock;
CaseRangeBlock = createBasicBlock("sw.caserange");
CurFn->getBasicBlockList().push_back(CaseRangeBlock);
Builder.SetInsertPoint(CaseRangeBlock);
// Emit range check.
llvm::Value *Diff =
Builder.CreateSub(SwitchInsn->getCondition(), llvm::ConstantInt::get(LHS),
"tmp");
llvm::Value *Cond =
Builder.CreateICmpULE(Diff, llvm::ConstantInt::get(Range), "tmp");
Builder.CreateCondBr(Cond, CaseDest, FalseDest);
// Restore the appropriate insertion point.
if (RestoreBB)
Builder.SetInsertPoint(RestoreBB);
else
Builder.ClearInsertionPoint();
void CodeGenFunction::EmitCaseStmt(const CaseStmt &S) {
if (S.getRHS()) {
EmitCaseStmtRange(S);
return;
}
EmitBlock(createBasicBlock("sw.bb"));
llvm::BasicBlock *CaseDest = Builder.GetInsertBlock();
llvm::APSInt CaseVal = S.getLHS()->EvaluateAsInt(getContext());
SwitchInsn->addCase(llvm::ConstantInt::get(CaseVal), CaseDest);
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitDefaultStmt(const DefaultStmt &S) {
llvm::BasicBlock *DefaultBlock = SwitchInsn->getDefaultDest();
assert(DefaultBlock->empty() &&
"EmitDefaultStmt: Default block already defined?");
EmitStmt(S.getSubStmt());
}
void CodeGenFunction::EmitSwitchStmt(const SwitchStmt &S) {
llvm::Value *CondV = EmitScalarExpr(S.getCond());
// Handle nested switch statements.
llvm::SwitchInst *SavedSwitchInsn = SwitchInsn;
llvm::BasicBlock *SavedCRBlock = CaseRangeBlock;
// Create basic block to hold stuff that comes after switch
// statement. We also need to create a default block now so that
// explicit case ranges tests can have a place to jump to on
// failure.
llvm::BasicBlock *NextBlock = createBasicBlock("sw.epilog");
llvm::BasicBlock *DefaultBlock = createBasicBlock("sw.default");
SwitchInsn = Builder.CreateSwitch(CondV, DefaultBlock);
CaseRangeBlock = DefaultBlock;
// Clear the insertion point to indicate we are in unreachable code.
Builder.ClearInsertionPoint();
// All break statements jump to NextBlock. If BreakContinueStack is non empty
// then reuse last ContinueBlock.
Anders Carlsson
committed
llvm::BasicBlock *ContinueBlock = 0;
if (!BreakContinueStack.empty())
ContinueBlock = BreakContinueStack.back().ContinueBlock;
Anders Carlsson
committed
// Ensure any vlas created between there and here, are undone
Anders Carlsson
committed
BreakContinueStack.push_back(BreakContinue(NextBlock, ContinueBlock));
// Emit switch body.
EmitStmt(S.getBody());
Anders Carlsson
committed
BreakContinueStack.pop_back();
// Update the default block in case explicit case range tests have
// been chained on top.
SwitchInsn->setSuccessor(0, CaseRangeBlock);
// If a default was never emitted then reroute any jumps to it and
// discard.
if (!DefaultBlock->getParent()) {
DefaultBlock->replaceAllUsesWith(NextBlock);
delete DefaultBlock;
}
// Emit continuation.
EmitBlock(NextBlock, true);
static std::string ConvertAsmString(const AsmStmt& S, bool &Failed)
{
// FIXME: No need to create new std::string here, we could just make sure
// that we don't read past the end of the string data.
std::string str(S.getAsmString()->getStrData(),
S.getAsmString()->getByteLength());
const char *Start = str.c_str();
unsigned NumOperands = S.getNumOutputs() + S.getNumInputs();
bool IsSimple = S.isSimple();
Failed = false;
static unsigned AsmCounter = 0;
AsmCounter++;
std::string Result;
if (IsSimple) {
while (*Start) {
switch (*Start) {
default:
Result += *Start;
break;
case '$':
Result += "$$";
break;
}
Start++;
}
return Result;
}
while (*Start) {
switch (*Start) {
default:
Result += *Start;
break;
case '$':
Result += "$$";
break;
case '%':
// Escaped character
Start++;
if (!*Start) {
// FIXME: This should be caught during Sema.
assert(0 && "Trailing '%' in asm string.");
}
char EscapedChar = *Start;
if (EscapedChar == '%') {
// Escaped percentage sign.
Result += '%';
} else if (EscapedChar == '=') {
// Generate an unique ID.
Result += llvm::utostr(AsmCounter);
} else if (isdigit(EscapedChar)) {
// %n - Assembler operand n
char *End;
unsigned long n = strtoul(Start, &End, 10);
if (Start == End) {
// FIXME: This should be caught during Sema.
assert(0 && "Missing operand!");
} else if (n >= NumOperands) {
// FIXME: This should be caught during Sema.
assert(0 && "Operand number out of range!");
}
Result += '$' + llvm::utostr(n);
} else if (isalpha(EscapedChar)) {
char *End;
unsigned long n = strtoul(Start + 1, &End, 10);
if (Start == End) {
// FIXME: This should be caught during Sema.
assert(0 && "Missing operand!");
} else if (n >= NumOperands) {
// FIXME: This should be caught during Sema.
assert(0 && "Operand number out of range!");
}
Result += "${" + llvm::utostr(n) + ':' + EscapedChar + '}';
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
} else if (EscapedChar == '[') {
std::string SymbolicName;
Start++;
while (*Start && *Start != ']') {
SymbolicName += *Start;
Start++;
}
if (!Start) {
// FIXME: Should be caught by sema.
assert(0 && "Could not parse symbolic name");
}
assert(*Start == ']' && "Error parsing symbolic name");
int Index = -1;
// Check if this is an output operand.
for (unsigned i = 0; i < S.getNumOutputs(); i++) {
if (S.getOutputName(i) == SymbolicName) {
Index = i;
break;
}
}
if (Index == -1) {
for (unsigned i = 0; i < S.getNumInputs(); i++) {
if (S.getInputName(i) == SymbolicName) {
Index = S.getNumOutputs() + i;
}
}
}
assert(Index != -1 && "Did not find right operand!");
Result += '$' + llvm::utostr(Index);
Failed = true;
return "";
}
}
Start++;
}
return Result;
}
static std::string SimplifyConstraint(const char* Constraint,
TargetInfo &Target,
const std::string *OutputNamesBegin = 0,
const std::string *OutputNamesEnd = 0)
{
std::string Result;
while (*Constraint) {
switch (*Constraint) {
default:
Result += Target.convertConstraint(*Constraint);
break;
// Ignore these
case '*':
case '?':
case '!':
break;
case 'g':
Result += "imr";
break;
case '[': {
assert(OutputNamesBegin && OutputNamesEnd &&
"Must pass output names to constraints with a symbolic name");
unsigned Index;
bool result = Target.resolveSymbolicName(Constraint,
OutputNamesBegin,
OutputNamesEnd, Index);
assert(result && "Could not resolve symbolic name"); result=result;
Result += llvm::utostr(Index);
break;
}
}
Constraint++;
}
return Result;
}
llvm::Value* CodeGenFunction::EmitAsmInput(const AsmStmt &S,
TargetInfo::ConstraintInfo Info,
const Expr *InputExpr,
std::string &ConstraintStr)
{
llvm::Value *Arg;
if ((Info & TargetInfo::CI_AllowsRegister) ||
!(Info & TargetInfo::CI_AllowsMemory)) {
const llvm::Type *Ty = ConvertType(InputExpr->getType());
if (Ty->isSingleValueType()) {
Arg = EmitScalarExpr(InputExpr);
} else {
LValue Dest = EmitLValue(InputExpr);
uint64_t Size = CGM.getTargetData().getTypeSizeInBits(Ty);
if (Size <= 64 && llvm::isPowerOf2_64(Size)) {
Ty = llvm::IntegerType::get(Size);
Ty = llvm::PointerType::getUnqual(Ty);
Arg = Builder.CreateLoad(Builder.CreateBitCast(Dest.getAddress(), Ty));
} else {
Arg = Dest.getAddress();
ConstraintStr += '*';
}
}
} else {
LValue Dest = EmitLValue(InputExpr);
Arg = Dest.getAddress();
ConstraintStr += '*';
}
return Arg;
}
void CodeGenFunction::EmitAsmStmt(const AsmStmt &S) {
bool Failed;
std::string AsmString =
ConvertAsmString(S, Failed);
if (Failed) {
ErrorUnsupported(&S, "asm string");
return;
}
std::string Constraints;
llvm::Value *ResultAddr = 0;
const llvm::Type *ResultType = llvm::Type::VoidTy;
std::vector<const llvm::Type*> ArgTypes;
std::vector<llvm::Value*> Args;
// Keep track of inout constraints.
std::string InOutConstraints;
std::vector<llvm::Value*> InOutArgs;
std::vector<const llvm::Type*> InOutArgTypes;
Anders Carlsson
committed
llvm::SmallVector<TargetInfo::ConstraintInfo, 4> OutputConstraintInfos;
for (unsigned i = 0, e = S.getNumOutputs(); i != e; i++) {
std::string OutputConstraint(S.getOutputConstraint(i)->getStrData(),
S.getOutputConstraint(i)->getByteLength());
TargetInfo::ConstraintInfo Info;
bool result = Target.validateOutputConstraint(OutputConstraint.c_str(),
Info);
assert(result && "Failed to parse output constraint"); result=result;
Anders Carlsson
committed
OutputConstraintInfos.push_back(Info);
// Simplify the output constraint.
OutputConstraint = SimplifyConstraint(OutputConstraint.c_str() + 1, Target);
LValue Dest = EmitLValue(S.getOutputExpr(i));
const llvm::Type *DestValueType =
cast<llvm::PointerType>(Dest.getAddress()->getType())->getElementType();
// If the first output operand is not a memory dest, we'll
// make it the return value.
if (i == 0 && !(Info & TargetInfo::CI_AllowsMemory) &&
DestValueType->isSingleValueType()) {
ResultAddr = Dest.getAddress();
ResultType = DestValueType;
Constraints += "=" + OutputConstraint;
} else {
ArgTypes.push_back(Dest.getAddress()->getType());
Args.push_back(Dest.getAddress());
if (i != 0)
Constraints += ',';
Constraints += OutputConstraint;
}
if (Info & TargetInfo::CI_ReadWrite) {
InOutConstraints += ',';
const Expr *InputExpr = S.getOutputExpr(i);
llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, InOutConstraints);
if (Info & TargetInfo::CI_AllowsRegister)
InOutConstraints += llvm::utostr(i);
else
InOutConstraints += OutputConstraint;
InOutArgTypes.push_back(Arg->getType());
InOutArgs.push_back(Arg);
}
}
unsigned NumConstraints = S.getNumOutputs() + S.getNumInputs();
for (unsigned i = 0, e = S.getNumInputs(); i != e; i++) {
const Expr *InputExpr = S.getInputExpr(i);
std::string InputConstraint(S.getInputConstraint(i)->getStrData(),
S.getInputConstraint(i)->getByteLength());
TargetInfo::ConstraintInfo Info;
bool result = Target.validateInputConstraint(InputConstraint.c_str(),
Anders Carlsson
committed
S.begin_output_names(),
S.end_output_names(),
Anders Carlsson
committed
&OutputConstraintInfos[0],
Info); result=result;
assert(result && "Failed to parse input constraint");
if (i != 0 || S.getNumOutputs() > 0)
Constraints += ',';
// Simplify the input constraint.
InputConstraint = SimplifyConstraint(InputConstraint.c_str(), Target,
S.begin_output_names(),
S.end_output_names());
llvm::Value *Arg = EmitAsmInput(S, Info, InputExpr, Constraints);
ArgTypes.push_back(Arg->getType());
Args.push_back(Arg);
Constraints += InputConstraint;
}
// Append the "input" part of inout constraints last.
for (unsigned i = 0, e = InOutArgs.size(); i != e; i++) {
ArgTypes.push_back(InOutArgTypes[i]);
Args.push_back(InOutArgs[i]);
}
Constraints += InOutConstraints;
// Clobbers
for (unsigned i = 0, e = S.getNumClobbers(); i != e; i++) {
std::string Clobber(S.getClobber(i)->getStrData(),
S.getClobber(i)->getByteLength());
Clobber = Target.getNormalizedGCCRegisterName(Clobber.c_str());
if (i != 0 || NumConstraints != 0)
Constraints += Clobber;
}
// Add machine specific clobbers
std::string MachineClobbers = Target.getClobbers();
if (!MachineClobbers.empty()) {
if (!Constraints.empty())
Constraints += ',';
Constraints += MachineClobbers;
const llvm::FunctionType *FTy =
llvm::FunctionType::get(ResultType, ArgTypes, false);