# HG changeset patch # User lindquist # Date 1214645873 -7200 # Node ID d59c363fccad27c41d0510d593e1d8ad468e1a12 # Parent 6b62e8cdf970255574b3833714d98dae3c7f6b87 [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. diff -r 6b62e8cdf970 -r d59c363fccad dmd/scope.h --- a/dmd/scope.h Sat Jun 28 05:57:16 2008 +0200 +++ b/dmd/scope.h Sat Jun 28 11:37:53 2008 +0200 @@ -29,6 +29,7 @@ struct AnonymousAggregateDeclaration; struct FuncDeclaration; struct DocComment; +struct EnclosingHandler; enum LINK; enum PROT; @@ -45,7 +46,7 @@ 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 diff -r 6b62e8cdf970 -r d59c363fccad dmd/statement.c --- a/dmd/statement.c Sat Jun 28 05:57:16 2008 +0200 +++ b/dmd/statement.c Sat Jun 28 11:37:53 2008 +0200 @@ -560,7 +560,7 @@ : Statement(loc) { statements = s; - enclosingtryfinally = NULL; + enclosinghandler = NULL; } Statement *UnrolledLoopStatement::syntaxCopy() @@ -582,7 +582,7 @@ { //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 @@ { condition = c; body = b; - enclosingtryfinally = NULL; + enclosinghandler = NULL; } Statement *WhileStatement::syntaxCopy() @@ -808,7 +808,7 @@ } #endif - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; condition = condition->semantic(sc); condition = resolveProperties(sc, condition); @@ -875,7 +875,7 @@ { body = b; condition = c; - enclosingtryfinally = NULL; + enclosinghandler = NULL; } Statement *DoStatement::syntaxCopy() @@ -887,7 +887,7 @@ Statement *DoStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; sc->noctor++; if (body) @@ -951,7 +951,7 @@ this->condition = condition; this->increment = increment; this->body = body; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *ForStatement::syntaxCopy() @@ -971,7 +971,7 @@ Statement *ForStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; ScopeDsymbol *sym = new ScopeDsymbol(); sym->parent = sc->scopesym; @@ -1085,7 +1085,7 @@ 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 @@ Type *tn = NULL; Type *tnv = NULL; - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; func = sc->func; if (func->fes) @@ -1981,7 +1981,7 @@ cases = NULL; hasNoDefault = 0; // LLVMDC - enclosingtryfinally = NULL; + enclosinghandler = NULL; } Statement *SwitchStatement::syntaxCopy() @@ -1996,7 +1996,7 @@ //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 @@ : Statement(loc) { sw = NULL; - enclosingtryfinally = NULL; + enclosinghandler = NULL; } Statement *GotoDefaultStatement::syntaxCopy() @@ -2295,7 +2295,7 @@ 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 @@ { cs = NULL; this->exp = exp; - enclosingtryfinally = NULL; + enclosinghandler = NULL; sw = NULL; } @@ -2332,7 +2332,7 @@ Statement *GotoCaseStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; if (exp) exp = exp->semantic(sc); @@ -2391,7 +2391,7 @@ : Statement(loc) { this->exp = exp; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *ReturnStatement::syntaxCopy() @@ -2406,7 +2406,7 @@ 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 @@ : Statement(loc) { this->ident = ident; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *BreakStatement::syntaxCopy() @@ -2678,7 +2678,7 @@ Statement *BreakStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; // If: // break Identifier; if (ident) @@ -2761,7 +2761,7 @@ : Statement(loc) { this->ident = ident; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *ContinueStatement::syntaxCopy() @@ -2772,7 +2772,7 @@ Statement *ContinueStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; //printf("ContinueStatement::semantic() %p\n", this); if (ident) { @@ -2866,6 +2866,8 @@ 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 @@ this->exp = NULL; this->body = body; this->esync = esync; + // LLVMDC + this->llsync = NULL; } Statement *SynchronizedStatement::syntaxCopy() @@ -2902,7 +2906,12 @@ } } if (body) - body = body->semantic(sc); + { + enclosinghandler = sc->tfOfTry; + sc->tfOfTry = new EnclosingSynchro(this); + body = body->semantic(sc); + sc->tfOfTry = enclosinghandler; + } return this; } @@ -3205,7 +3214,7 @@ { this->body = body; this->finalbody = finalbody; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *TryFinallyStatement::syntaxCopy() @@ -3219,10 +3228,10 @@ { //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 @@ : Statement(loc) { this->statement = statement; + this->enclosinghandler = NULL; } Statement *VolatileStatement::syntaxCopy() @@ -3410,7 +3420,13 @@ 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 @@ this->ident = ident; this->label = NULL; this->tf = NULL; - this->enclosingtryfinally = NULL; + this->enclosinghandler = NULL; } Statement *GotoStatement::syntaxCopy() @@ -3471,7 +3487,7 @@ //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 @@ 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 @@ else ls->statement = this; tf = sc->tf; - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; sc = sc->push(); sc->scopesym = sc->enclosing->scopesym; sc->callSuper |= CSXlabel; diff -r 6b62e8cdf970 -r d59c363fccad dmd/statement.h --- a/dmd/statement.h Sat Jun 28 05:57:16 2008 +0200 +++ b/dmd/statement.h Sat Jun 28 11:37:53 2008 +0200 @@ -50,6 +50,8 @@ struct InterState; struct CaseStatement; struct LabelStatement; +struct VolatileStatement; +struct SynchronizedStatement; enum TOK; @@ -77,6 +79,35 @@ #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 UnrolledLoopStatement : Statement { Statements *statements; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; UnrolledLoopStatement(Loc loc, Statements *statements); Statement *syntaxCopy(); @@ -241,7 +272,7 @@ { Expression *condition; Statement *body; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; WhileStatement(Loc loc, Expression *c, Statement *b); Statement *syntaxCopy(); @@ -263,7 +294,7 @@ { Statement *body; Expression *condition; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; DoStatement(Loc loc, Statement *b, Expression *c); Statement *syntaxCopy(); @@ -287,7 +318,7 @@ 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 @@ Arguments *arguments; // array of Argument*'s Expression *aggr; Statement *body; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; VarDeclaration *key; VarDeclaration *value; @@ -409,7 +440,7 @@ 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 GotoDefaultStatement : Statement { SwitchStatement *sw; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; GotoDefaultStatement(Loc loc); Statement *syntaxCopy(); @@ -500,7 +531,7 @@ { 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 ReturnStatement : Statement { Expression *exp; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; ReturnStatement(Loc loc, Expression *exp); Statement *syntaxCopy(); @@ -546,7 +577,7 @@ struct BreakStatement : Statement { Identifier *ident; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; BreakStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -564,7 +595,7 @@ struct ContinueStatement : Statement { Identifier *ident; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; ContinueStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -583,6 +614,7 @@ { Expression *exp; Statement *body; + EnclosingHandler* enclosinghandler; SynchronizedStatement(Loc loc, Expression *exp, Statement *body); Statement *syntaxCopy(); @@ -599,6 +631,7 @@ elem *esync; SynchronizedStatement(Loc loc, elem *esync, Statement *body); void toIR(IRState *irs); + llvm::Value* llsync; }; struct WithStatement : Statement @@ -656,7 +689,7 @@ { Statement *body; Statement *finalbody; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; TryFinallyStatement(Loc loc, Statement *body, Statement *finalbody); Statement *syntaxCopy(); @@ -705,6 +738,7 @@ struct VolatileStatement : Statement { Statement *statement; + EnclosingHandler* enclosinghandler; VolatileStatement(Loc loc, Statement *statement); Statement *syntaxCopy(); @@ -723,7 +757,7 @@ Identifier *ident; LabelDsymbol *label; TryFinallyStatement *tf; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; GotoStatement(Loc loc, Identifier *ident); Statement *syntaxCopy(); @@ -741,7 +775,7 @@ Identifier *ident; Statement *statement; TryFinallyStatement *tf; - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; block *lblock; // back end int isReturnLabel; @@ -798,7 +832,7 @@ struct AsmBlockStatement : CompoundStatement { - TryFinallyStatement *enclosingtryfinally; + EnclosingHandler* enclosinghandler; AsmBlockStatement(Loc loc, Statements *s); Statements *flatten(Scope *sc); diff -r 6b62e8cdf970 -r d59c363fccad gen/asmstmt.cpp --- a/gen/asmstmt.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/asmstmt.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -381,7 +381,7 @@ 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 @@ 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 @@ // necessary for in-asm branches Statement *AsmBlockStatement::semantic(Scope *sc) { - enclosingtryfinally = sc->tfOfTry; + enclosinghandler = sc->tfOfTry; return CompoundStatement::semantic(sc); } diff -r 6b62e8cdf970 -r d59c363fccad gen/classes.cpp --- a/gen/classes.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/classes.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -1253,7 +1253,7 @@ 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) diff -r 6b62e8cdf970 -r d59c363fccad gen/irstate.cpp --- a/gen/irstate.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/irstate.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -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(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; diff -r 6b62e8cdf970 -r d59c363fccad gen/irstate.h --- a/gen/irstate.h Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/irstate.h Sat Jun 28 11:37:53 2008 +0200 @@ -23,7 +23,7 @@ struct Module; struct TypeStruct; struct BaseClass; -struct TryFinallyStatement; +struct EnclosingHandler; struct IrModule; @@ -44,10 +44,10 @@ // 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 @@ llvm::Module* module; // interface info type, used in DtoInterfaceInfoType - llvm::StructType* interfaceInfoType; + const LLStructType* interfaceInfoType; + const LLStructType* mutexType; // functions typedef std::vector FunctionVector; diff -r 6b62e8cdf970 -r d59c363fccad gen/llvm.h --- a/gen/llvm.h Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/llvm.h Sat Jun 28 11:37:53 2008 +0200 @@ -20,25 +20,25 @@ // 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 diff -r 6b62e8cdf970 -r d59c363fccad gen/llvmhelpers.cpp --- a/gen/llvmhelpers.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/llvmhelpers.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -174,7 +174,7 @@ /*//////////////////////////////////////////////////////////////////////////////////////// // GOTO HELPER ////////////////////////////////////////////////////////////////////////////////////////*/ -void DtoGoto(Loc* loc, Identifier* target, TryFinallyStatement* enclosingtryfinally) +void DtoGoto(Loc* loc, Identifier* target, EnclosingHandler* enclosinghandler) { assert(!gIR->scopereturned()); @@ -189,44 +189,117 @@ 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 ////////////////////////////////////////////////////////////////////////////////////////*/ diff -r 6b62e8cdf970 -r d59c363fccad gen/llvmhelpers.h --- a/gen/llvmhelpers.h Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/llvmhelpers.h Sat Jun 28 11:37:53 2008 +0200 @@ -16,12 +16,22 @@ // 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); diff -r 6b62e8cdf970 -r d59c363fccad gen/runtime.cpp --- a/gen/runtime.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/runtime.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -852,10 +852,32 @@ 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 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 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); + } +} diff -r 6b62e8cdf970 -r d59c363fccad gen/statements.cpp --- a/gen/statements.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/statements.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -70,12 +70,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ //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 @@ 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 @@ 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; idim; ++i) { @@ -974,7 +964,7 @@ } // 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 @@ 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 @@ 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 @@ 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,56 +1112,47 @@ ////////////////////////////////////////////////////////////////////////////// +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); + // enter lock + if (exp) + { + 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); } ////////////////////////////////////////////////////////////////////////////// -/* this has moved to asmstmt.cpp -void AsmStatement::toIR(IRState* p) -{ - 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 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); -} -*/ -////////////////////////////////////////////////////////////////////////////// - void VolatileStatement::toIR(IRState* p) { Logger::println("VolatileStatement::toIR(): %s", loc.toChars()); @@ -1181,8 +1162,7 @@ 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 @@ // 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 @@ } // restore volatile state - gIR->func()->inVolatile = old; + // FIXME } ////////////////////////////////////////////////////////////////////////////// diff -r 6b62e8cdf970 -r d59c363fccad gen/tollvm.cpp --- a/gen/tollvm.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/tollvm.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -637,6 +637,7 @@ size_t getABITypeSize(const LLType* t) { + Logger::cout() << "getting abi type of: " << *t << '\n'; return gTargetData->getABITypeSize(t); } @@ -677,12 +678,49 @@ return gIR->interfaceInfoType; } +////////////////////////////////////////////////////////////////////////////////////////// +const LLStructType* DtoMutexType() +{ + if (gIR->mutexType) + return gIR->mutexType; + // win32 + if (global.params.isWindows) + { + // CRITICAL_SECTION.sizeof == 68 + std::vector types(17, LLType::Int32Ty); + return LLStructType::get(types); + } - + // pthread_fastlock + std::vector types2; + types2.push_back(DtoSize_t()); + types2.push_back(LLType::Int32Ty); + const LLStructType* fastlock = LLStructType::get(types2); - + // pthread_mutex + std::vector 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 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; +} diff -r 6b62e8cdf970 -r d59c363fccad gen/tollvm.h --- a/gen/tollvm.h Sat Jun 28 05:57:16 2008 +0200 +++ b/gen/tollvm.h Sat Jun 28 11:37:53 2008 +0200 @@ -39,6 +39,7 @@ // 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); diff -r 6b62e8cdf970 -r d59c363fccad ir/irfunction.cpp --- a/ir/irfunction.cpp Sat Jun 28 05:57:16 2008 +0200 +++ b/ir/irfunction.cpp Sat Jun 28 11:37:53 2008 +0200 @@ -1,3 +1,5 @@ + +#include "gen/llvm.h" #include "gen/tollvm.h" #include "ir/irfunction.h" @@ -27,9 +29,4 @@ srcfileArg = NULL; msgArg = NULL; - inVolatile = false; } - -IrFunction::~IrFunction() -{ -} diff -r 6b62e8cdf970 -r d59c363fccad ir/irfunction.h --- a/ir/irfunction.h Sat Jun 28 05:57:16 2008 +0200 +++ b/ir/irfunction.h Sat Jun 28 11:37:53 2008 +0200 @@ -25,10 +25,7 @@ llvm::AllocaInst* srcfileArg; llvm::AllocaInst* msgArg; - bool inVolatile; - IrFunction(FuncDeclaration* fd); - virtual ~IrFunction(); }; #endif