From 0d160ffc767e5149cff35ada0c7410dc0020a450 Mon Sep 17 00:00:00 2001 From: Tomas Lindquist Olsen Date: Sat, 28 Jun 2008 11:37:53 +0200 Subject: [PATCH] [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. --- dmd/scope.h | 3 +- dmd/statement.c | 80 ++++++++++++++++------------ dmd/statement.h | 64 +++++++++++++++++------ gen/asmstmt.cpp | 6 +-- gen/classes.cpp | 2 +- gen/irstate.cpp | 7 ++- gen/irstate.h | 9 ++-- gen/llvm.h | 32 ++++++------ gen/llvmhelpers.cpp | 99 ++++++++++++++++++++++++++++++----- gen/llvmhelpers.h | 14 ++++- gen/runtime.cpp | 34 +++++++++--- gen/statements.cpp | 124 +++++++++++++++++++------------------------- gen/tollvm.cpp | 42 ++++++++++++++- gen/tollvm.h | 1 + ir/irfunction.cpp | 7 +-- ir/irfunction.h | 3 -- 16 files changed, 350 insertions(+), 177 deletions(-) diff --git a/dmd/scope.h b/dmd/scope.h index 1460d8b2..780fe345 100644 --- a/dmd/scope.h +++ b/dmd/scope.h @@ -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 diff --git a/dmd/statement.c b/dmd/statement.c index d28f96eb..9d4839dc 100644 --- a/dmd/statement.c +++ b/dmd/statement.c @@ -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) - 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 @@ 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; diff --git a/dmd/statement.h b/dmd/statement.h index a330adf2..ca4cda60 100644 --- a/dmd/statement.h +++ b/dmd/statement.h @@ -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); diff --git a/gen/asmstmt.cpp b/gen/asmstmt.cpp index 1f0c122f..689c645d 100644 --- a/gen/asmstmt.cpp +++ b/gen/asmstmt.cpp @@ -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); } diff --git a/gen/classes.cpp b/gen/classes.cpp index 080b8b6e..9c4b4eb3 100644 --- a/gen/classes.cpp +++ b/gen/classes.cpp @@ -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) diff --git a/gen/irstate.cpp b/gen/irstate.cpp index c929f19d..4dc0e81c 100644 --- a/gen/irstate.cpp +++ b/gen/irstate.cpp @@ -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; diff --git a/gen/irstate.h b/gen/irstate.h index f4aa9024..f8cd69ab 100644 --- a/gen/irstate.h +++ b/gen/irstate.h @@ -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 FunctionVector; diff --git a/gen/llvm.h b/gen/llvm.h index 169aca05..3dd3af12 100644 --- a/gen/llvm.h +++ b/gen/llvm.h @@ -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 diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 6c97e953..cd742c69 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -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 diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index c86065d0..15e41f40 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -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); diff --git a/gen/runtime.cpp b/gen/runtime.cpp index b2e6d4e6..33dee756 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -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 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 --git a/gen/statements.cpp b/gen/statements.cpp index 7047670e..694ec525 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -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; idim; ++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,56 +1112,47 @@ 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); + // 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 @@ 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 } ////////////////////////////////////////////////////////////////////////////// diff --git a/gen/tollvm.cpp b/gen/tollvm.cpp index 5ead5c69..0f00b2e5 100644 --- a/gen/tollvm.cpp +++ b/gen/tollvm.cpp @@ -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 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 --git a/gen/tollvm.h b/gen/tollvm.h index db763263..110c801b 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -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); diff --git a/ir/irfunction.cpp b/ir/irfunction.cpp index 703a49a7..08a34616 100644 --- a/ir/irfunction.cpp +++ b/ir/irfunction.cpp @@ -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() -{ } diff --git a/ir/irfunction.h b/ir/irfunction.h index 1e569eb3..16671f8c 100644 --- a/ir/irfunction.h +++ b/ir/irfunction.h @@ -25,10 +25,7 @@ struct IrFunction : IrBase llvm::AllocaInst* srcfileArg; llvm::AllocaInst* msgArg; - bool inVolatile; - IrFunction(FuncDeclaration* fd); - virtual ~IrFunction(); }; #endif