changeset 309:d59c363fccad trunk

[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.
author lindquist
date Sat, 28 Jun 2008 11:37:53 +0200
parents 6b62e8cdf970
children d20cf0dec9c1
files dmd/scope.h dmd/statement.c dmd/statement.h gen/asmstmt.cpp gen/classes.cpp gen/irstate.cpp gen/irstate.h gen/llvm.h gen/llvmhelpers.cpp gen/llvmhelpers.h gen/runtime.cpp gen/statements.cpp gen/tollvm.cpp gen/tollvm.h ir/irfunction.cpp ir/irfunction.h
diffstat 16 files changed, 348 insertions(+), 175 deletions(-) [+]
line wrap: on
line diff
--- 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
--- 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;
--- 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);
--- 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);
 }
--- 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)
--- 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;
--- 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<IrFunction*> FunctionVector;
--- 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
 
--- 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
 ////////////////////////////////////////////////////////////////////////////////////////*/
 
--- 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);
--- 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<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);
+    }
+}
--- 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; i<statements->dim; ++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<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);
-}
-*/
-//////////////////////////////////////////////////////////////////////////////
-
 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
 }
 
 //////////////////////////////////////////////////////////////////////////////
--- 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<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;
+}
--- 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);
--- 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()
-{
-}
--- 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