[svn r330] Implemented synchronized statements.

Changed the tryfinally handlers to a more generalized EnclosingHandler.
Changed ClassInfoS to be mutable so they can be used as locks.
Added new BB after throw ala return/break etc.
This commit is contained in:
Tomas Lindquist Olsen 2008-06-28 11:37:53 +02:00
parent ac3744a59d
commit 0d160ffc76
16 changed files with 350 additions and 177 deletions

View file

@ -29,6 +29,7 @@ struct AggregateDeclaration;
struct AnonymousAggregateDeclaration;
struct FuncDeclaration;
struct DocComment;
struct EnclosingHandler;
enum LINK;
enum PROT;
@ -45,7 +46,7 @@ struct Scope
LabelStatement *slabel; // enclosing labelled statement
SwitchStatement *sw; // enclosing switch statement
TryFinallyStatement *tf; // enclosing try finally statement; set inside its finally block
TryFinallyStatement *tfOfTry; // enclosing try finally statement; set inside its try block
EnclosingHandler *tfOfTry; // enclosing try-finally, volatile or synchronized statement; set inside its try or body block
Statement *sbreak; // enclosing statement that supports "break"
Statement *scontinue; // enclosing statement that supports "continue"
ForeachStatement *fes; // if nested function for ForeachStatement, this is it

View file

@ -560,7 +560,7 @@ UnrolledLoopStatement::UnrolledLoopStatement(Loc loc, Statements *s)
: Statement(loc)
{
statements = s;
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
Statement *UnrolledLoopStatement::syntaxCopy()
@ -582,7 +582,7 @@ Statement *UnrolledLoopStatement::semantic(Scope *sc)
{
//printf("UnrolledLoopStatement::semantic(this = %p, sc = %p)\n", this, sc);
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
sc->noctor++;
Scope *scd = sc->push();
@ -773,7 +773,7 @@ WhileStatement::WhileStatement(Loc loc, Expression *c, Statement *b)
{
condition = c;
body = b;
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
Statement *WhileStatement::syntaxCopy()
@ -808,7 +808,7 @@ Statement *WhileStatement::semantic(Scope *sc)
}
#endif
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
@ -875,7 +875,7 @@ DoStatement::DoStatement(Loc loc, Statement *b, Expression *c)
{
body = b;
condition = c;
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
Statement *DoStatement::syntaxCopy()
@ -887,7 +887,7 @@ Statement *DoStatement::syntaxCopy()
Statement *DoStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
sc->noctor++;
if (body)
@ -951,7 +951,7 @@ ForStatement::ForStatement(Loc loc, Statement *init, Expression *condition, Expr
this->condition = condition;
this->increment = increment;
this->body = body;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *ForStatement::syntaxCopy()
@ -971,7 +971,7 @@ Statement *ForStatement::syntaxCopy()
Statement *ForStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
ScopeDsymbol *sym = new ScopeDsymbol();
sym->parent = sc->scopesym;
@ -1085,7 +1085,7 @@ ForeachStatement::ForeachStatement(Loc loc, enum TOK op, Arguments *arguments,
this->arguments = arguments;
this->aggr = aggr;
this->body = body;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
this->key = NULL;
this->value = NULL;
@ -1114,7 +1114,7 @@ Statement *ForeachStatement::semantic(Scope *sc)
Type *tn = NULL;
Type *tnv = NULL;
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
func = sc->func;
if (func->fes)
@ -1981,7 +1981,7 @@ SwitchStatement::SwitchStatement(Loc loc, Expression *c, Statement *b)
cases = NULL;
hasNoDefault = 0;
// LLVMDC
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
Statement *SwitchStatement::syntaxCopy()
@ -1996,7 +1996,7 @@ Statement *SwitchStatement::semantic(Scope *sc)
//printf("SwitchStatement::semantic(%p)\n", this);
assert(!cases); // ensure semantic() is only run once
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
condition = condition->semantic(sc);
condition = resolveProperties(sc, condition);
@ -2284,7 +2284,7 @@ GotoDefaultStatement::GotoDefaultStatement(Loc loc)
: Statement(loc)
{
sw = NULL;
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
Statement *GotoDefaultStatement::syntaxCopy()
@ -2295,7 +2295,7 @@ Statement *GotoDefaultStatement::syntaxCopy()
Statement *GotoDefaultStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
sw = sc->sw;
if (!sw)
error("goto default not in switch statement");
@ -2319,7 +2319,7 @@ GotoCaseStatement::GotoCaseStatement(Loc loc, Expression *exp)
{
cs = NULL;
this->exp = exp;
enclosingtryfinally = NULL;
enclosinghandler = NULL;
sw = NULL;
}
@ -2332,7 +2332,7 @@ Statement *GotoCaseStatement::syntaxCopy()
Statement *GotoCaseStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
if (exp)
exp = exp->semantic(sc);
@ -2391,7 +2391,7 @@ ReturnStatement::ReturnStatement(Loc loc, Expression *exp)
: Statement(loc)
{
this->exp = exp;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *ReturnStatement::syntaxCopy()
@ -2406,7 +2406,7 @@ Statement *ReturnStatement::syntaxCopy()
Statement *ReturnStatement::semantic(Scope *sc)
{
//printf("ReturnStatement::semantic() %s\n", toChars());
this->enclosingtryfinally = sc->tfOfTry;
this->enclosinghandler = sc->tfOfTry;
FuncDeclaration *fd = sc->parent->isFuncDeclaration();
Scope *scx = sc;
@ -2667,7 +2667,7 @@ BreakStatement::BreakStatement(Loc loc, Identifier *ident)
: Statement(loc)
{
this->ident = ident;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *BreakStatement::syntaxCopy()
@ -2678,7 +2678,7 @@ Statement *BreakStatement::syntaxCopy()
Statement *BreakStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
// If:
// break Identifier;
if (ident)
@ -2761,7 +2761,7 @@ ContinueStatement::ContinueStatement(Loc loc, Identifier *ident)
: Statement(loc)
{
this->ident = ident;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *ContinueStatement::syntaxCopy()
@ -2772,7 +2772,7 @@ Statement *ContinueStatement::syntaxCopy()
Statement *ContinueStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
//printf("ContinueStatement::semantic() %p\n", this);
if (ident)
{
@ -2866,6 +2866,8 @@ SynchronizedStatement::SynchronizedStatement(Loc loc, Expression *exp, Statement
this->exp = exp;
this->body = body;
this->esync = NULL;
// LLVMDC
this->llsync = NULL;
}
SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *body)
@ -2874,6 +2876,8 @@ SynchronizedStatement::SynchronizedStatement(Loc loc, elem *esync, Statement *bo
this->exp = NULL;
this->body = body;
this->esync = esync;
// LLVMDC
this->llsync = NULL;
}
Statement *SynchronizedStatement::syntaxCopy()
@ -2902,7 +2906,12 @@ Statement *SynchronizedStatement::semantic(Scope *sc)
}
}
if (body)
{
enclosinghandler = sc->tfOfTry;
sc->tfOfTry = new EnclosingSynchro(this);
body = body->semantic(sc);
sc->tfOfTry = enclosinghandler;
}
return this;
}
@ -3205,7 +3214,7 @@ TryFinallyStatement::TryFinallyStatement(Loc loc, Statement *body, Statement *fi
{
this->body = body;
this->finalbody = finalbody;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *TryFinallyStatement::syntaxCopy()
@ -3219,10 +3228,10 @@ Statement *TryFinallyStatement::semantic(Scope *sc)
{
//printf("TryFinallyStatement::semantic()\n");
enclosingtryfinally = sc->tfOfTry;
sc->tfOfTry = this;
enclosinghandler = sc->tfOfTry;
sc->tfOfTry = new EnclosingTryFinally(this);
body = body->semantic(sc);
sc->tfOfTry = enclosingtryfinally;
sc->tfOfTry = enclosinghandler;
sc = sc->push();
sc->tf = this;
@ -3399,6 +3408,7 @@ VolatileStatement::VolatileStatement(Loc loc, Statement *statement)
: Statement(loc)
{
this->statement = statement;
this->enclosinghandler = NULL;
}
Statement *VolatileStatement::syntaxCopy()
@ -3410,7 +3420,13 @@ Statement *VolatileStatement::syntaxCopy()
Statement *VolatileStatement::semantic(Scope *sc)
{
statement = statement ? statement->semantic(sc) : NULL;
if (statement)
{
enclosinghandler = sc->tfOfTry;
sc->tfOfTry = new EnclosingVolatile(this);
statement = statement->semantic(sc);
sc->tfOfTry = enclosinghandler;
}
return this;
}
@ -3457,7 +3473,7 @@ GotoStatement::GotoStatement(Loc loc, Identifier *ident)
this->ident = ident;
this->label = NULL;
this->tf = NULL;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
}
Statement *GotoStatement::syntaxCopy()
@ -3471,7 +3487,7 @@ Statement *GotoStatement::semantic(Scope *sc)
//printf("GotoStatement::semantic()\n");
tf = sc->tf;
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
label = fd->searchLabel(ident);
if (!label->statement && sc->fes)
{
@ -3515,7 +3531,7 @@ LabelStatement::LabelStatement(Loc loc, Identifier *ident, Statement *statement)
this->ident = ident;
this->statement = statement;
this->tf = NULL;
this->enclosingtryfinally = NULL;
this->enclosinghandler = NULL;
this->lblock = NULL;
this->isReturnLabel = 0;
this->llvmBB = NULL;
@ -3539,7 +3555,7 @@ Statement *LabelStatement::semantic(Scope *sc)
else
ls->statement = this;
tf = sc->tf;
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
sc = sc->push();
sc->scopesym = sc->enclosing->scopesym;
sc->callSuper |= CSXlabel;

View file

@ -50,6 +50,8 @@ struct HdrGenState;
struct InterState;
struct CaseStatement;
struct LabelStatement;
struct VolatileStatement;
struct SynchronizedStatement;
enum TOK;
@ -77,6 +79,35 @@ struct block;
#endif
struct code;
// LLVMDC this is used for tracking try-finally, synchronized and volatile scopes
// definitions in gen/llvmhelpers.cpp
struct EnclosingHandler : Object
{
virtual void emitCode(IRState* p) = 0;
virtual EnclosingHandler* getEnclosing() = 0;
};
struct EnclosingTryFinally : EnclosingHandler
{
TryFinallyStatement* tf;
void emitCode(IRState* p);
EnclosingHandler* getEnclosing();
EnclosingTryFinally(TryFinallyStatement* _tf) : tf(_tf) {}
};
struct EnclosingVolatile : EnclosingHandler
{
VolatileStatement* v;
void emitCode(IRState* p);
EnclosingHandler* getEnclosing();
EnclosingVolatile(VolatileStatement* _tf) : v(_tf) {}
};
struct EnclosingSynchro : EnclosingHandler
{
SynchronizedStatement* s;
void emitCode(IRState* p);
EnclosingHandler* getEnclosing();
EnclosingSynchro(SynchronizedStatement* _tf) : s(_tf) {}
};
struct Statement : Object
{
Loc loc;
@ -196,7 +227,7 @@ struct CompoundStatement : Statement
struct UnrolledLoopStatement : Statement
{
Statements *statements;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
UnrolledLoopStatement(Loc loc, Statements *statements);
Statement *syntaxCopy();
@ -241,7 +272,7 @@ struct WhileStatement : Statement
{
Expression *condition;
Statement *body;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
WhileStatement(Loc loc, Expression *c, Statement *b);
Statement *syntaxCopy();
@ -263,7 +294,7 @@ struct DoStatement : Statement
{
Statement *body;
Expression *condition;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
DoStatement(Loc loc, Statement *b, Expression *c);
Statement *syntaxCopy();
@ -287,7 +318,7 @@ struct ForStatement : Statement
Expression *condition;
Expression *increment;
Statement *body;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
ForStatement(Loc loc, Statement *init, Expression *condition, Expression *increment, Statement *body);
Statement *syntaxCopy();
@ -312,7 +343,7 @@ struct ForeachStatement : Statement
Arguments *arguments; // array of Argument*'s
Expression *aggr;
Statement *body;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
VarDeclaration *key;
VarDeclaration *value;
@ -409,7 +440,7 @@ struct SwitchStatement : Statement
Expression *condition;
Statement *body;
DefaultStatement *sdefault;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
Array gotoCases; // array of unresolved GotoCaseStatement's
Array *cases; // array of CaseStatement's
@ -484,7 +515,7 @@ struct DefaultStatement : Statement
struct GotoDefaultStatement : Statement
{
SwitchStatement *sw;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
GotoDefaultStatement(Loc loc);
Statement *syntaxCopy();
@ -500,7 +531,7 @@ struct GotoCaseStatement : Statement
{
Expression *exp; // NULL, or which case to goto
CaseStatement *cs; // case statement it resolves to
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
SwitchStatement *sw;
GotoCaseStatement(Loc loc, Expression *exp);
@ -525,7 +556,7 @@ struct SwitchErrorStatement : Statement
struct ReturnStatement : Statement
{
Expression *exp;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
ReturnStatement(Loc loc, Expression *exp);
Statement *syntaxCopy();
@ -546,7 +577,7 @@ struct ReturnStatement : Statement
struct BreakStatement : Statement
{
Identifier *ident;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
BreakStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
@ -564,7 +595,7 @@ struct BreakStatement : Statement
struct ContinueStatement : Statement
{
Identifier *ident;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
ContinueStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
@ -583,6 +614,7 @@ struct SynchronizedStatement : Statement
{
Expression *exp;
Statement *body;
EnclosingHandler* enclosinghandler;
SynchronizedStatement(Loc loc, Expression *exp, Statement *body);
Statement *syntaxCopy();
@ -599,6 +631,7 @@ struct SynchronizedStatement : Statement
elem *esync;
SynchronizedStatement(Loc loc, elem *esync, Statement *body);
void toIR(IRState *irs);
llvm::Value* llsync;
};
struct WithStatement : Statement
@ -656,7 +689,7 @@ struct TryFinallyStatement : Statement
{
Statement *body;
Statement *finalbody;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody);
Statement *syntaxCopy();
@ -705,6 +738,7 @@ struct ThrowStatement : Statement
struct VolatileStatement : Statement
{
Statement *statement;
EnclosingHandler* enclosinghandler;
VolatileStatement(Loc loc, Statement *statement);
Statement *syntaxCopy();
@ -723,7 +757,7 @@ struct GotoStatement : Statement
Identifier *ident;
LabelDsymbol *label;
TryFinallyStatement *tf;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
GotoStatement(Loc loc, Identifier *ident);
Statement *syntaxCopy();
@ -741,7 +775,7 @@ struct LabelStatement : Statement
Identifier *ident;
Statement *statement;
TryFinallyStatement *tf;
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
block *lblock; // back end
int isReturnLabel;
@ -798,7 +832,7 @@ struct AsmStatement : Statement
struct AsmBlockStatement : CompoundStatement
{
TryFinallyStatement *enclosingtryfinally;
EnclosingHandler* enclosinghandler;
AsmBlockStatement(Loc loc, Statements *s);
Statements *flatten(Scope *sc);

View file

@ -381,7 +381,7 @@ assert(0);
AsmBlockStatement::AsmBlockStatement(Loc loc, Statements* s)
: CompoundStatement(loc, s)
{
enclosingtryfinally = NULL;
enclosinghandler = NULL;
}
// rewrite argument indices to the block scope indices
@ -638,7 +638,7 @@ void AsmBlockStatement::toIR(IRState* p)
sw->addCase(llvm::ConstantInt::get(llvm::IntegerType::get(32), it->first), casebb);
p->scope() = IRScope(casebb,bb);
DtoGoto(&loc, it->second, enclosingtryfinally);
DtoGoto(&loc, it->second, enclosinghandler);
}
p->scope() = IRScope(bb,oldend);
@ -669,7 +669,7 @@ Statement *AsmBlockStatement::syntaxCopy()
// necessary for in-asm branches
Statement *AsmBlockStatement::semantic(Scope *sc)
{
enclosingtryfinally = sc->tfOfTry;
enclosinghandler = sc->tfOfTry;
return CompoundStatement::semantic(sc);
}

View file

@ -1253,7 +1253,7 @@ void DtoDeclareClassInfo(ClassDeclaration* cd)
const LLType* st = cinfo->type->ir.type->get();
cd->ir.irStruct->classInfo = new llvm::GlobalVariable(st, true, DtoLinkage(cd), NULL, gname, gIR->module);
cd->ir.irStruct->classInfo = new llvm::GlobalVariable(st, false, DtoLinkage(cd), NULL, gname, gIR->module);
}
static LLConstant* build_offti_entry(ClassDeclaration* cd, VarDeclaration* vd)

View file

@ -10,6 +10,7 @@
#include "mtype.h"
#include "declaration.h"
#include "statement.h"
#include "gen/irstate.h"
#include "tollvm.h"
@ -35,19 +36,21 @@ IRLoopScope::IRLoopScope()
{
}
IRLoopScope::IRLoopScope(Statement* s, TryFinallyStatement* enclosingtryfinally, llvm::BasicBlock* b, llvm::BasicBlock* e)
IRLoopScope::IRLoopScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* b, llvm::BasicBlock* e)
{
begin = b;
end = e;
//builder.SetInsertPoint(b);
this->s = s;
this->enclosingtryfinally = enclosingtryfinally;
this->enclosinghandler = enclosinghandler;
}
//////////////////////////////////////////////////////////////////////////////////////////
IRState::IRState()
{
interfaceInfoType = NULL;
mutexType = NULL;
dmodule = 0;
module = 0;
emitMain = false;

View file

@ -23,7 +23,7 @@ struct FuncDeclaration;
struct Module;
struct TypeStruct;
struct BaseClass;
struct TryFinallyStatement;
struct EnclosingHandler;
struct IrModule;
@ -44,10 +44,10 @@ struct IRLoopScope : IRScope
// generating statement
Statement* s;
// the try of a TryFinally that encloses the loop
TryFinallyStatement* enclosingtryfinally;
EnclosingHandler* enclosinghandler;
IRLoopScope();
IRLoopScope(Statement* s, TryFinallyStatement* enclosingtryfinally, llvm::BasicBlock* b, llvm::BasicBlock* e);
IRLoopScope(Statement* s, EnclosingHandler* enclosinghandler, llvm::BasicBlock* b, llvm::BasicBlock* e);
};
struct IRBuilderHelper
@ -96,7 +96,8 @@ struct IRState
llvm::Module* module;
// interface info type, used in DtoInterfaceInfoType
llvm::StructType* interfaceInfoType;
const LLStructType* interfaceInfoType;
const LLStructType* mutexType;
// functions
typedef std::vector<IrFunction*> FunctionVector;

View file

@ -20,25 +20,25 @@ using llvm::IRBuilder;
// shortcuts for the common llvm types
typedef llvm::Type LLType;
typedef llvm::FunctionType LLFunctionType;
typedef llvm::PointerType LLPointerType;
typedef llvm::StructType LLStructType;
typedef llvm::ArrayType LLArrayType;
typedef llvm::IntegerType LLIntegerType;
typedef llvm::OpaqueType LLOpaqueType;
#define LLType llvm::Type
#define LLFunctionType llvm::FunctionType
#define LLPointerType llvm::PointerType
#define LLStructType llvm::StructType
#define LLArrayType llvm::ArrayType
#define LLIntegerType llvm::IntegerType
#define LLOpaqueType llvm::OpaqueType
typedef llvm::Value LLValue;
typedef llvm::GlobalValue LLGlobalValue;
typedef llvm::GlobalVariable LLGlobalVariable;
typedef llvm::Function LLFunction;
#define LLValue llvm::Value
#define LLGlobalValue llvm::GlobalValue
#define LLGlobalVariable llvm::GlobalVariable
#define LLFunction llvm::Function
typedef llvm::Constant LLConstant;
typedef llvm::ConstantStruct LLConstantStruct;
typedef llvm::ConstantArray LLConstantArray;
typedef llvm::ConstantInt LLConstantInt;
#define LLConstant llvm::Constant
#define LLConstantStruct llvm::ConstantStruct
#define LLConstantArray llvm::ConstantArray
#define LLConstantInt llvm::ConstantInt
typedef llvm::PATypeHolder LLPATypeHolder;
#define LLPATypeHolder llvm::PATypeHolder
#define LLSmallVector llvm::SmallVector

View file

@ -174,7 +174,7 @@ LabelStatement* DtoLabelStatement(Identifier* ident)
/*////////////////////////////////////////////////////////////////////////////////////////
// GOTO HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally)
void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler)
{
assert(!gIR->scopereturned());
@ -189,42 +189,115 @@ void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfina
lblstmt->llvmBB = llvm::BasicBlock::Create("label", gIR->topfunc());
// find finallys between goto and label
TryFinallyStatement* endfinally = enclosingtryfinally;
while(endfinally != NULL && endfinally != lblstmt->enclosingtryfinally) {
endfinally = endfinally->enclosingtryfinally;
EnclosingHandler* endfinally = enclosinghandler;
while(endfinally != NULL && endfinally != lblstmt->enclosinghandler) {
endfinally = endfinally->getEnclosing();
}
// error if didn't find tf statement of label
if(endfinally != lblstmt->enclosingtryfinally)
if(endfinally != lblstmt->enclosinghandler)
error("cannot goto into try block", loc->toChars());
// emit code for finallys between goto and label
DtoFinallyBlocks(enclosingtryfinally, endfinally);
DtoEnclosingHandlers(enclosinghandler, endfinally);
llvm::BranchInst::Create(lblstmt->llvmBB, gIR->scopebb());
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// TRY FINALLY HELPER
// TRY-FINALLY, VOLATILE AND SYNCHRONIZED HELPER
////////////////////////////////////////////////////////////////////////////////////////*/
void DtoFinallyBlocks(TryFinallyStatement* start, TryFinallyStatement* end)
void EnclosingSynchro::emitCode(IRState * p)
{
if (s->exp)
DtoLeaveMonitor(s->llsync);
else
DtoLeaveCritical(s->llsync);
}
EnclosingHandler* EnclosingSynchro::getEnclosing()
{
return s->enclosinghandler;
}
////////////////////////////////////////////////////////////////////////////////////////
void EnclosingVolatile::emitCode(IRState * p)
{
// store-load barrier
DtoMemoryBarrier(false, false, true, false);
}
EnclosingHandler* EnclosingVolatile::getEnclosing()
{
return v->enclosinghandler;
}
////////////////////////////////////////////////////////////////////////////////////////
void EnclosingTryFinally::emitCode(IRState * p)
{
assert(tf->finalbody);
tf->finalbody->toIR(p);
}
EnclosingHandler* EnclosingTryFinally::getEnclosing()
{
return tf->enclosinghandler;
}
////////////////////////////////////////////////////////////////////////////////////////
void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end)
{
// verify that end encloses start
TryFinallyStatement* endfinally = start;
EnclosingHandler* endfinally = start;
while(endfinally != NULL && endfinally != end) {
endfinally = endfinally->enclosingtryfinally;
endfinally = endfinally->getEnclosing();
}
assert(endfinally == end);
// emit code for finallys between start and end
TryFinallyStatement* tf = start;
EnclosingHandler* tf = start;
while(tf != end) {
tf->finalbody->toIR(gIR);
tf = tf->enclosingtryfinally;
tf->emitCode(gIR);
tf = tf->getEnclosing();
}
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// SYNCHRONIZED SECTION HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/
void DtoEnterCritical(LLValue* g)
{
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_criticalenter");
gIR->ir->CreateCall(fn, g, "");
}
void DtoLeaveCritical(LLValue* g)
{
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_criticalexit");
gIR->ir->CreateCall(fn, g, "");
}
void DtoEnterMonitor(LLValue* v)
{
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_monitorenter");
v = DtoBitCast(v, fn->getFunctionType()->getParamType(0));
gIR->ir->CreateCall(fn, v, "");
}
void DtoLeaveMonitor(LLValue* v)
{
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_monitorexit");
v = DtoBitCast(v, fn->getFunctionType()->getParamType(0));
gIR->ir->CreateCall(fn, v, "");
}
/****************************************************************************************/
/*////////////////////////////////////////////////////////////////////////////////////////
// NESTED VARIABLE HELPERS

View file

@ -16,12 +16,22 @@ void DtoAssert(Loc* loc, DValue* msg);
// return the LabelStatement from the current function with the given identifier or NULL if not found
LabelStatement* DtoLabelStatement(Identifier* ident);
// emit goto
void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally);
void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosingtryfinally);
// generates IR for finally blocks between the 'start' and 'end' statements
// will begin with the finally block belonging to 'start' and does not include
// the finally block of 'end'
void DtoFinallyBlocks(TryFinallyStatement* start, TryFinallyStatement* end);
void DtoEnclosingHandlers(EnclosingHandler* start, EnclosingHandler* end);
// enters a critical section
void DtoEnterCritical(LLValue* g);
// leaves a critical section
void DtoLeaveCritical(LLValue* g);
// enters a monitor lock
void DtoEnterMonitor(LLValue* v);
// leaves a monitor lock
void DtoLeaveMonitor(LLValue* v);
// nested variable/class helpers
LLValue* DtoNestedContext(FuncDeclaration* func);

View file

@ -852,10 +852,32 @@ static void LLVM_D_BuildRuntimeModule()
palist = palist.addAttr(2, llvm::ParamAttr::ByVal);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)->setParamAttrs(palist);
}
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// void _d_criticalenter(D_CRITICAL_SECTION *dcs)
// void _d_criticalexit(D_CRITICAL_SECTION *dcs)
{
std::string fname("_d_criticalenter");
std::string fname2("_d_criticalexit");
std::vector<const LLType*> types;
types.push_back(rt_ptr(DtoMutexType()));
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
}
// void _d_monitorenter(Object h)
// void _d_monitorexit(Object h)
{
std::string fname("_d_monitorenter");
std::string fname2("_d_monitorexit");
std::vector<const LLType*> types;
types.push_back(objectTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
}
}

View file

@ -70,12 +70,7 @@ void ReturnStatement::toIR(IRState* p)
if (!e->inPlace())
DtoAssign(rvar, e);
DtoFinallyBlocks(enclosingtryfinally, NULL);
if (f->inVolatile) {
// store-load barrier
DtoMemoryBarrier(false, false, true, false);
}
DtoEnclosingHandlers(enclosinghandler, NULL);
if (global.params.symdebug) DtoDwarfFuncEnd(f->decl);
llvm::ReturnInst::Create(p->scopebb());
@ -95,12 +90,7 @@ void ReturnStatement::toIR(IRState* p)
Logger::cout() << "return value after cast: " << *v << '\n';
}
DtoFinallyBlocks(enclosingtryfinally, NULL);
if (gIR->func()->inVolatile) {
// store-load barrier
DtoMemoryBarrier(false, false, true, false);
}
DtoEnclosingHandlers(enclosinghandler, NULL);
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
llvm::ReturnInst::Create(v, p->scopebb());
@ -109,12 +99,7 @@ void ReturnStatement::toIR(IRState* p)
else
{
assert(p->topfunc()->getReturnType() == LLType::VoidTy);
DtoFinallyBlocks(enclosingtryfinally, NULL);
if (gIR->func()->inVolatile) {
// store-load barrier
DtoMemoryBarrier(false, false, true, false);
}
DtoEnclosingHandlers(enclosinghandler, NULL);
if (global.params.symdebug) DtoDwarfFuncEnd(p->func()->decl);
llvm::ReturnInst::Create(p->scopebb());
@ -275,7 +260,7 @@ void WhileStatement::toIR(IRState* p)
gIR->scope() = IRScope(whilebodybb,endbb);
// while body code
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,whilebb,endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,whilebb,endbb));
body->toIR(p);
p->loopbbs.pop_back();
@ -310,7 +295,7 @@ void DoStatement::toIR(IRState* p)
gIR->scope() = IRScope(dowhilebb,endbb);
// do-while body code
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,dowhilebb,endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,dowhilebb,endbb));
body->toIR(p);
p->loopbbs.pop_back();
@ -351,7 +336,7 @@ void ForStatement::toIR(IRState* p)
assert(!gIR->scopereturned());
llvm::BranchInst::Create(forbb, gIR->scopebb());
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,forincbb,endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,forincbb,endbb));
// replace current scope
gIR->scope() = IRScope(forbb,forbodybb);
@ -410,7 +395,7 @@ void BreakStatement::toIR(IRState* p)
if (ident != 0) {
Logger::println("ident = %s", ident->toChars());
DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler);
// get the loop statement the label refers to
Statement* targetLoopStatement = target->statement;
@ -431,7 +416,7 @@ void BreakStatement::toIR(IRState* p)
assert(found);
}
else {
DtoFinallyBlocks(enclosingtryfinally, p->loopbbs.back().enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, p->loopbbs.back().enclosinghandler);
llvm::BranchInst::Create(p->loopbbs.back().end, p->scopebb());
}
@ -454,7 +439,7 @@ void ContinueStatement::toIR(IRState* p)
if (ident != 0) {
Logger::println("ident = %s", ident->toChars());
DtoFinallyBlocks(enclosingtryfinally, target->enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, target->enclosinghandler);
// get the loop statement the label refers to
Statement* targetLoopStatement = target->statement;
@ -473,7 +458,7 @@ void ContinueStatement::toIR(IRState* p)
assert(0);
}
else {
DtoFinallyBlocks(enclosingtryfinally, gIR->loopbbs.back().enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, gIR->loopbbs.back().enclosinghandler);
llvm::BranchInst::Create(gIR->loopbbs.back().begin, gIR->scopebb());
}
}
@ -599,6 +584,11 @@ void ThrowStatement::toIR(IRState* p)
//Logger::cout() << "arg: " << *arg << '\n';
gIR->ir->CreateCall(fn, arg, "");
gIR->ir->CreateUnreachable();
// need a block after the throw for now
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* bb = llvm::BasicBlock::Create("afterthrow", p->topfunc(), oldend);
p->scope() = IRScope(bb,oldend);
}
//////////////////////////////////////////////////////////////////////////////
@ -767,7 +757,7 @@ void SwitchStatement::toIR(IRState* p)
assert(body);
p->scope() = IRScope(bodybb, endbb);
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb));
body->toIR(p);
p->loopbbs.pop_back();
@ -851,7 +841,7 @@ void UnrolledLoopStatement::toIR(IRState* p)
llvm::BasicBlock* endbb = llvm::BasicBlock::Create("unrolledend", p->topfunc(), oldend);
p->scope() = IRScope(p->scopebb(),endbb);
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,p->scopebb(),endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,p->scopebb(),endbb));
for (int i=0; i<statements->dim; ++i)
{
@ -974,7 +964,7 @@ void ForeachStatement::toIR(IRState* p)
}
// emit body
p->loopbbs.push_back(IRLoopScope(this,enclosingtryfinally,nextbb,endbb));
p->loopbbs.push_back(IRLoopScope(this,enclosinghandler,nextbb,endbb));
body->toIR(p);
p->loopbbs.pop_back();
@ -1047,7 +1037,7 @@ void GotoStatement::toIR(IRState* p)
llvm::BasicBlock* oldend = gIR->scopeend();
llvm::BasicBlock* bb = llvm::BasicBlock::Create("aftergoto", p->topfunc(), oldend);
DtoGoto(&loc, label->ident, enclosingtryfinally);
DtoGoto(&loc, label->ident, enclosinghandler);
p->scope() = IRScope(bb,oldend);
}
@ -1068,7 +1058,7 @@ void GotoDefaultStatement::toIR(IRState* p)
assert(!p->scopereturned());
assert(sw->sdefault->bodyBB);
DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler);
llvm::BranchInst::Create(sw->sdefault->bodyBB, p->scopebb());
p->scope() = IRScope(bb,oldend);
@ -1093,7 +1083,7 @@ void GotoCaseStatement::toIR(IRState* p)
cs->bodyBB = llvm::BasicBlock::Create("goto_case", p->topfunc(), p->scopeend());
}
DtoFinallyBlocks(enclosingtryfinally, sw->enclosingtryfinally);
DtoEnclosingHandlers(enclosinghandler, sw->enclosinghandler);
llvm::BranchInst::Create(cs->bodyBB, p->scopebb());
p->scope() = IRScope(bb,oldend);
@ -1122,54 +1112,45 @@ void WithStatement::toIR(IRState* p)
//////////////////////////////////////////////////////////////////////////////
static LLConstant* generate_unique_critical_section()
{
const LLType* Mty = DtoMutexType();
return new llvm::GlobalVariable(Mty, false, llvm::GlobalValue::InternalLinkage, LLConstant::getNullValue(Mty), ".uniqueCS", gIR->module);
}
void SynchronizedStatement::toIR(IRState* p)
{
Logger::println("SynchronizedStatement::toIR(): %s", loc.toChars());
LOG_SCOPE;
Logger::attention(loc, "synchronized is currently ignored. only the body will be emitted");
if (global.params.symdebug)
DtoDwarfStopPoint(loc.linnum);
body->toIR(p);
}
//////////////////////////////////////////////////////////////////////////////
/* this has moved to asmstmt.cpp
void AsmStatement::toIR(IRState* p)
// enter lock
if (exp)
{
Logger::println("AsmStatement::toIR(): %s", loc.toChars());
LOG_SCOPE;
// error("%s: inline asm is not yet implemented", loc.toChars());
// fatal();
assert(!asmcode && !asmalign && !refparam && !naked && !regs);
Token* t = tokens;
assert(t);
std::string asmstr;
do {
Logger::println("token: %s", t->toChars());
asmstr.append(t->toChars());
asmstr.append(" ");
} while (t = t->next);
Logger::println("asm expr = '%s'", asmstr.c_str());
// create function type
std::vector<const LLType*> args;
const llvm::FunctionType* fty = llvm::FunctionType::get(DtoSize_t(), args, false);
// create inline asm callee
llvm::InlineAsm* inasm = llvm::InlineAsm::get(fty, asmstr, "r,r", false);
assert(0);
llsync = exp->toElem(p)->getRVal();
DtoEnterMonitor(llsync);
}
*/
else
{
llsync = generate_unique_critical_section();
DtoEnterCritical(llsync);
}
// emit body
body->toIR(p);
// exit lock
// no point in a unreachable unlock, terminating statements must insert this themselves.
if (p->scopereturned())
return;
else if (exp)
DtoLeaveMonitor(llsync);
else
DtoLeaveCritical(llsync);
}
//////////////////////////////////////////////////////////////////////////////
void VolatileStatement::toIR(IRState* p)
@ -1181,8 +1162,7 @@ void VolatileStatement::toIR(IRState* p)
DtoDwarfStopPoint(loc.linnum);
// mark in-volatile
bool old = gIR->func()->inVolatile;
gIR->func()->inVolatile = true;
// FIXME
// has statement
if (statement != NULL)
@ -1193,7 +1173,7 @@ void VolatileStatement::toIR(IRState* p)
// do statement
statement->toIR(p);
// no point in a unreachable barrier, terminating statements should insert this themselves.
// no point in a unreachable barrier, terminating statements must insert this themselves.
if (statement->fallOffEnd())
{
// store-load
@ -1208,7 +1188,7 @@ void VolatileStatement::toIR(IRState* p)
}
// restore volatile state
gIR->func()->inVolatile = old;
// FIXME
}
//////////////////////////////////////////////////////////////////////////////

View file

@ -637,6 +637,7 @@ size_t getTypeStoreSize(const LLType* t)
size_t getABITypeSize(const LLType* t)
{
Logger::cout() << "getting abi type of: " << *t << '\n';
return gTargetData->getABITypeSize(t);
}
@ -677,12 +678,49 @@ const LLStructType* DtoInterfaceInfoType()
return gIR->interfaceInfoType;
}
//////////////////////////////////////////////////////////////////////////////////////////
const LLStructType* DtoMutexType()
{
if (gIR->mutexType)
return gIR->mutexType;
// win32
if (global.params.isWindows)
{
// CRITICAL_SECTION.sizeof == 68
std::vector<const LLType*> types(17, LLType::Int32Ty);
return LLStructType::get(types);
}
// pthread_fastlock
std::vector<const LLType*> types2;
types2.push_back(DtoSize_t());
types2.push_back(LLType::Int32Ty);
const LLStructType* fastlock = LLStructType::get(types2);
// pthread_mutex
std::vector<const LLType*> types1;
types1.push_back(LLType::Int32Ty);
types1.push_back(LLType::Int32Ty);
types1.push_back(getVoidPtrType());
types1.push_back(LLType::Int32Ty);
types1.push_back(fastlock);
const LLStructType* pmutex = LLStructType::get(types1);
// D_CRITICAL_SECTION
LLOpaqueType* opaque = LLOpaqueType::get();
std::vector<const LLType*> types;
types.push_back(getPtrToType(opaque));
types.push_back(pmutex);
// resolve type
pmutex = LLStructType::get(types);
LLPATypeHolder pa(pmutex);
opaque->refineAbstractTypeTo(pa.get());
pmutex = isaStruct(pa.get());
gIR->mutexType = pmutex;
gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex);
return pmutex;
}

View file

@ -39,6 +39,7 @@ LLValue* DtoBoolean(LLValue* val);
// some types
const LLType* DtoSize_t();
const LLStructType* DtoInterfaceInfoType();
const LLStructType* DtoMutexType();
// getelementptr helpers
LLValue* DtoGEP1(LLValue* ptr, LLValue* i0, const char* var=NULL, llvm::BasicBlock* bb=NULL);

View file

@ -1,3 +1,5 @@
#include "gen/llvm.h"
#include "gen/tollvm.h"
#include "ir/irfunction.h"
@ -27,9 +29,4 @@ IrFunction::IrFunction(FuncDeclaration* fd)
srcfileArg = NULL;
msgArg = NULL;
inVolatile = false;
}
IrFunction::~IrFunction()
{
}

View file

@ -25,10 +25,7 @@ struct IrFunction : IrBase
llvm::AllocaInst* srcfileArg;
llvm::AllocaInst* msgArg;
bool inVolatile;
IrFunction(FuncDeclaration* fd);
virtual ~IrFunction();
};
#endif