Browse Source

Added ThreadedGlobal variable scope. Resolves #538.

Extended attrs flags.
Brucey 4 years ago
parent
commit
1ae8e70657
6 changed files with 185 additions and 119 deletions
  1. 73 24
      ctranslator.bmx
  2. 63 57
      decl.bmx
  3. 12 12
      iparser.bmx
  4. 1 1
      options.bmx
  5. 35 24
      parser.bmx
  6. 1 1
      toker.bmx

+ 73 - 24
ctranslator.bmx

@@ -918,7 +918,7 @@ t:+"NULLNULLNULL"
 
 		If Not gdecl.funcGlobal Then
 			If Not (gdecl.attrs & DECL_INITONLY) Then
-				glob :+"static " + TransType( gdecl.init.exprType, gdecl.munged )+" "
+				glob :+"static " + TransThreadedGlobal(gdecl) + TransType( gdecl.init.exprType, gdecl.munged )+" "
 			End If
 	
 			glob :+ gdecl.munged+"="
@@ -948,7 +948,7 @@ t:+"NULLNULLNULL"
 					Else If Not TConstExpr(gdecl.init) And Not (gdecl.attrs & DECL_INITONLY) Then
 						' for non const, we need to add an initialiser
 						glob :+ TransValue(gdecl.ty, "") + ";~n"
-						glob :+ indent +"static int _" + gdecl.munged + "_inited = 0;~n"
+						glob :+ indent +"static " + TransThreadedGlobal(gdecl) + " int _" + gdecl.munged + "_inited = 0;~n"
 						glob :+ indent + "if (!_" + gdecl.munged + "_inited) {~n"
 						glob :+ indent + "~t_" + gdecl.munged + "_inited = 1;~n"
 						glob :+ indent + "~t" + gdecl.munged + " = " + gdecl.init.Trans() + ";~n"
@@ -968,7 +968,7 @@ t:+"NULLNULLNULL"
 				End If
 			End If
 		Else
-			glob :+ "static int _" + gdecl.munged + "_inited = 0;~n"
+			glob :+ "static " + TransThreadedGlobal(gdecl) + " int _" + gdecl.munged + "_inited = 0;~n"
 			glob :+ indent + "if (!_" + gdecl.munged + "_inited) {~n"
 			glob :+ indent + "~t_" + gdecl.munged + "_inited = 1;~n"
 			glob :+ indent + "~t" + gdecl.munged + " = " 
@@ -1062,6 +1062,14 @@ t:+"NULLNULLNULL"
 		EndIf
 		InternalErr "TCTranslator.TransStatic"
 	End Method
+	
+	Method TransThreadedGlobal:String( decl:TDecl )
+		If decl.attrs & DECL_THREADED Then
+			Return "BBThreadLocal "
+		Else
+			Return ""
+		End If
+	End Method
 
 	Method TransTemplateCast$( ty:TType,src:TType,expr$ )
 
@@ -2852,6 +2860,7 @@ t:+"NULLNULLNULL"
 	End Method
 
 	Method EmitDebugEnterScope(block:TBlockDecl)
+		Local scopeIndex:Int
 		Local count:Int
 		For Local decl:TDecl = EachIn block.Decls()
 			If TLocalDecl(decl) Then
@@ -2896,11 +2905,12 @@ t:+"NULLNULLNULL"
 				Emit Enquote(TransDebugScopeType(TClassDecl(block.scope).objectType)) + ","
 				Emit ".var_address=&o"
 				Emit "},"
+				scopeIndex:+ 1
 			End If
 			
 			' block globals
 			For Local gdecl:TGlobalDecl = EachIn block.Decls()
-				EmitGlobalDebugScope(gdecl)
+				EmitGlobalDebugScope(gdecl, scopeIndex)
 			Next
 			
 			' iterate through decls and add as appropriate
@@ -2930,9 +2940,26 @@ t:+"NULLNULLNULL"
 			
 		Emit "};"
 		
+		' threaded global
+		For Local gdecl:TGlobalDecl = EachIn block.Decls()
+			If gdecl.IsThreaded() Then
+				Emit "__scope.decls[" + gdecl.scopeIndex + "].var_address = &" + gdecl.munged + ";"
+			End If
+		Next
+		
 		Emit "bbOnDebugEnterScope(&__scope);"
 	End Method
 	
+	Method EmitClassThreadedGlobalDebugInit(classDecl:TClassDecl)
+		Local classid:String = classDecl.munged
+		' classid + "_scope
+		For Local decl:TGlobalDecl = EachIn classDecl.Decls()
+			If decl.IsThreaded() Then
+				Emit classid + "_scope.decls[" + decl.scopeIndex + "].var_address = &" + decl.munged + ";"
+			End If
+		Next
+	End Method
+	
 	Method TransDebugNullObjectError:String(variable:String, cdecl:TClassDecl)
 		If cdecl.IsStruct() Or cdecl.ident = "String" Or cdecl.ident = "___Array" Then
 			'Return cdecl.munged + "NullObjectTest(" + variable + ")"
@@ -3618,9 +3645,9 @@ End Rem
 			decl.Semant()
 
 			If TFunctionPtrType(decl.ty) Then
-					Emit "extern " + TransRefType( decl.ty, decl.munged ) + ";"
+				Emit "extern " + TransThreadedGlobal(decl) + TransRefType( decl.ty, decl.munged ) + ";"
 			Else
-				Emit "extern "+TransRefType( decl.ty, "" )+" "+ decl.munged+";"
+				Emit "extern " + TransThreadedGlobal(decl) +TransRefType( decl.ty, "" )+" "+ decl.munged+";"
 			End If
 		Next
 
@@ -3964,10 +3991,11 @@ End Rem
 		EndIf
 	End Method
 	
-	Method EmitClassConstsDebugScope(classDecl:TClassDecl)
+	Method EmitClassConstsDebugScope(classDecl:TClassDecl, scopeIndex:Int Var)
 	
 		For Local decl:TConstDecl = EachIn classDecl.Decls()
 			EmitConstDebugScope(decl)
+			scopeIndex :+ 1
 		Next
 
 	End Method
@@ -3986,7 +4014,7 @@ End Rem
 
 	End Method
 
-	Method EmitClassFieldsDebugScope(classDecl:TClassDecl)
+	Method EmitClassFieldsDebugScope(classDecl:TClassDecl, scopeIndex:Int Var)
 
 		' Don't list superclass fields in our debug scope
 		'If classDecl.superClass Then
@@ -4018,6 +4046,7 @@ End Rem
 			'End If
 			Emit "},"
 			
+			scopeIndex :+ 1
 			'offset:+ decl.ty.GetSize()
 		Next
 		
@@ -4163,18 +4192,24 @@ End Rem
 
 	End Method
 	
-	Method EmitClassGlobalDebugScope( classDecl:TClassDecl )
+	Method EmitClassGlobalDebugScope( classDecl:TClassDecl, scopeIndex:Int Var )
 		For Local decl:TGlobalDecl = EachIn classDecl.Decls()
-			EmitGlobalDebugScope(decl)
+			EmitGlobalDebugScope(decl, scopeIndex)
+			scopeIndex :+ 1
 		Next
 	End Method
 
-	Method EmitGlobalDebugScope( decl:TGlobalDecl )
+	Method EmitGlobalDebugScope( decl:TGlobalDecl, scopeIndex:Int )
 		Emit "{"
 		Emit "BBDEBUGDECL_GLOBAL,"
 		Emit Enquote(decl.ident) + ","
 		Emit Enquote(TransDebugScopeType(decl.ty)) + ","
-		Emit ".var_address=(void*)&" + decl.munged
+		If decl.IsThreaded() Then
+			Emit ".var_address=0"
+			decl.scopeIndex = scopeIndex
+		Else
+			Emit ".var_address=(void*)&" + decl.munged
+		End If
 		Emit "},"
 	End Method
 
@@ -4365,9 +4400,9 @@ End Rem
 				Local gdecl:TGlobalDecl =TGlobalDecl( decl )
 				If gdecl
 					If TFunctionPtrType(gdecl.ty) Then
-						Emit TransRefType( gdecl.ty, gdecl.munged ) + ";"
+						Emit TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, gdecl.munged ) + ";"
 					Else
-						Emit TransRefType( gdecl.ty, "" )+" "+gdecl.munged+";"
+						Emit TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, "" )+" "+ gdecl.munged+";"
 					End If
 					Continue
 				EndIf
@@ -4404,14 +4439,16 @@ End Rem
 
 		Emit "{"
 		
+		Local scopeIndex:Int
+		
 		' debug const decls
-		EmitClassConstsDebugScope(classDecl)
+		EmitClassConstsDebugScope(classDecl, scopeIndex)
 		
 		' debug field decls
-		EmitClassFieldsDebugScope(classDecl)
+		EmitClassFieldsDebugScope(classDecl, scopeIndex)
 		
 		' debug global decls
-		EmitClassGlobalDebugScope(classDecl)
+		EmitClassGlobalDebugScope(classDecl, scopeIndex)
 		
 		' debug func decls
 		EmitClassFuncsDebugScope(classDecl)
@@ -6023,12 +6060,12 @@ End Rem
 				
 If Not gdecl.IsPrivate() Then
 				If Not TFunctionPtrType(gdecl.ty) Then
-					Emit "extern "+TransRefType( gdecl.ty, "" )+" "+gdecl.munged+";"	'forward reference...
+					Emit "extern "+TransThreadedGlobal(gdecl)+TransRefType( gdecl.ty, "" )+" "+gdecl.munged+";"	'forward reference...
 				Else
 					If Not TFunctionPtrType(gdecl.ty).func.noCastGen Then
 						' generate function pointer refs if we haven't been told not to
 '						If Not gdecl.IsExtern() Then
-							Emit "extern " + TransRefType( gdecl.ty, gdecl.munged )+";"	'forward reference...
+							Emit "extern " + TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, gdecl.munged )+";"	'forward reference...
 '						End If
 					End If
 				End If
@@ -6273,7 +6310,8 @@ If Not gdecl.IsExtern() Then
 						Emit TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
 Else
 					' delcare in source for any references to it locally in this module
-					Emit "extern "+TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
+					
+					Emit "extern "+ TransThreadedGlobal(gdecl) +TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
 End If
 					End If
 				Else
@@ -6289,11 +6327,10 @@ End If
 		For Local gdecl:TGlobalDecl=EachIn app.SemantedGlobals
 			If gdecl And gdecl.funcGlobal Then
 				MungDecl gdecl
-				
 				If Not TFunctionPtrType(gdecl.ty) Then
-					Emit "static " + TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
+					Emit "static " + TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, "WW" )+" "+gdecl.munged+";"
 				Else
-					Emit "static " + TransRefType( gdecl.ty, gdecl.munged ) + ";"
+					Emit "static " + TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, gdecl.munged ) + ";"
 				End If
 				Continue
 			End If
@@ -6311,7 +6348,7 @@ End If
 				
 				If Not TFunctionPtrType(gdecl.ty) And Not gdecl.IsPrivate() Then
 					If TConstExpr(gdecl.init) Then
-						Emit TransRefType( gdecl.ty, "WW" )+" "+TransGlobalDecl(gdecl)+";"
+						Emit TransThreadedGlobal(gdecl) + TransRefType( gdecl.ty, "WW" )+" "+TransGlobalDecl(gdecl)+";"
 						gdecl.inited = True
 					Else
 If Not gdecl.IsExtern() Then
@@ -6406,6 +6443,18 @@ End If
 		If first Then
 			Emit "GC_add_roots(&" + first.munged + ", &" + last.munged + " + 1);"
 		End If
+		
+		' threaded global scope assignments
+		For Local decl:TDecl=EachIn app.Semanted()
+
+			If decl.declImported Continue
+
+			Local cdecl:TClassDecl=TClassDecl( decl )
+			If cdecl
+				EmitClassThreadedGlobalDebugInit(cdecl)
+			End If
+
+		Next
 
 		' register incbins
 		For Local ib:TIncbin = EachIn app.incbins

+ 63 - 57
decl.bmx

@@ -22,40 +22,41 @@
 '    distribution.
 '
 
-Const DECL_EXTERN:Int=        $010000
-Const DECL_PRIVATE:Int=       $020000
-Const DECL_ABSTRACT:Int=      $040000
-Const DECL_FINAL:Int=         $080000
-Const DECL_READ_ONLY:Int=     $000100
-Const DECL_STATIC:Int=      $20000000
-Const DECL_OVERRIDE:Int=    $40000000
-Const DECL_INLINE:Int=      $80000000
-
-Const DECL_SEMANTED:Int=      $100000
-Const DECL_SEMANTING:Int=     $200000
-Const DECL_CYCLIC:Int=       $8000000
-
-Const DECL_POINTER:Int=       $400000
-
-Const DECL_ARG:Int=           $800000
-Const DECL_INITONLY:Int=     $1000000
-
-Const DECL_NODEBUG:Int=      $2000000
-Const DECL_PROTECTED:Int=    $4000000
-Const DECL_EXPORT:Int=       $8000000
-
-Const DECL_API_CDECL:Int=   $00000000
-Const DECL_API_STDCALL:Int= $10000000
-Const DECL_API_DEFAULT:Int=DECL_API_CDECL
-Const DECL_API_FLAGS:Int=   DECL_API_CDECL | DECL_API_STDCALL
-
-Const DECL_NESTED:Int=      $20000000
-
-Const CLASS_INTERFACE:Int=    $002000
-Const CLASS_THROWABLE:Int=    $004000
-Const CLASS_STRUCT:Int=       $008000
-Const CLASS_GENERIC:Int=      $001000
-Const CLASS_FLAGS:Int = CLASS_INTERFACE | CLASS_THROWABLE | CLASS_STRUCT | CLASS_GENERIC
+Const DECL_EXTERN:Long=        $010000
+Const DECL_PRIVATE:Long=       $020000
+Const DECL_ABSTRACT:Long=      $040000
+Const DECL_FINAL:Long=         $080000
+Const DECL_READ_ONLY:Long=     $000100
+Const DECL_STATIC:Long=      $20000000
+Const DECL_OVERRIDE:Long=    $40000000
+Const DECL_INLINE:Long=      $80000000
+Const DECL_THREADED:Long=   $100000000:Long
+
+Const DECL_SEMANTED:Long=      $100000
+Const DECL_SEMANTING:Long=     $200000
+Const DECL_CYCLIC:Long=       $8000000
+
+Const DECL_POINTER:Long=       $400000
+
+Const DECL_ARG:Long=           $800000
+Const DECL_INITONLY:Long=     $1000000
+
+Const DECL_NODEBUG:Long=      $2000000
+Const DECL_PROTECTED:Long=    $4000000
+Const DECL_EXPORT:Long=       $8000000
+
+Const DECL_API_CDECL:Long=   $00000000
+Const DECL_API_STDCALL:Long= $10000000
+Const DECL_API_DEFAULT:Long=DECL_API_CDECL
+Const DECL_API_FLAGS:Long=   DECL_API_CDECL | DECL_API_STDCALL
+
+Const DECL_NESTED:Long=      $20000000
+
+Const CLASS_INTERFACE:Long=    $002000
+Const CLASS_THROWABLE:Long=    $004000
+Const CLASS_STRUCT:Long=       $008000
+Const CLASS_GENERIC:Long=      $001000
+Const CLASS_FLAGS:Long = CLASS_INTERFACE | CLASS_THROWABLE | CLASS_STRUCT | CLASS_GENERIC
 
 Const SCOPE_FUNC:Int = 0
 Const SCOPE_CLASS_LOCAL:Int = 1
@@ -144,13 +145,14 @@ Type TDecl
 	Field errInfo$
 	Field actual:TDecl
 	Field scope:TScopeDecl
-	Field attrs:Int
+	Field attrs:Long
 	Field metadata:TMetadata = New TMetadata
 	
 	Field declImported:Int = False
 	Field generated:Int
 	
 	Field _identLower:String
+	Field scopeIndex:Int = -1
 	
 	Method New()
 		errInfo=_errInfo
@@ -218,6 +220,10 @@ Type TDecl
 		Return (attrs & DECL_NODEBUG)<>0
 	End Method
 	
+	Method IsThreaded:Int()
+		Return (attrs & DECL_THREADED)<>0
+	End Method
+	
 	Method FuncScope:TFuncDecl()
 		If TFuncDecl( Self ) Return TFuncDecl( Self )
 		If scope Return scope.FuncScope()
@@ -580,7 +586,7 @@ End Type
 Type TConstDecl Extends TValDecl
 	Field value$
 	
-	Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Int )
+	Method Create:TConstDecl( ident$,ty:TType,init:TExpr,attrs:Long )
 		Self.ident=ident
 		Self.munged=ident
 		Self.declTy=ty
@@ -632,7 +638,7 @@ Type TLocalDecl Extends TVarDecl
 	Field volatile:Int = False
 	Field declaredInTry:TTryStmtDecl
 
-	Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False, volatile:Int = False )
+	Method Create:TLocalDecl( ident$,ty:TType,init:TExpr,attrs:Long=0, generated:Int = False, volatile:Int = False )
 		Self.ident=ident
 		Self.declTy=ty
 		Self.declInit=init
@@ -678,7 +684,7 @@ Type TArgDecl Extends TLocalDecl
 
 	Field castTo:String
 	
-	Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Int=0, generated:Int = False, volatile:Int = True )
+	Method Create:TArgDecl( ident$,ty:TType,init:TExpr,attrs:Long=0, generated:Int = False, volatile:Int = True )
 		Self.ident=ident
 		Self.declTy=ty
 		Self.declInit=init
@@ -751,7 +757,7 @@ Type TGlobalDecl Extends TVarDecl
 	Field funcGlobal:Int
 	Field mscope:TScopeDecl
 	
-	Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Int=0,funcGlobal:Int=False )
+	Method Create:TGlobalDecl( ident$,ty:TType,init:TExpr,attrs:Long=0,funcGlobal:Int=False )
 		Self.deferInit = True
 		Self.ident=ident
 		Self.declTy=ty
@@ -805,7 +811,7 @@ Type TFieldDecl Extends TVarDecl
 	' location offset in object variable data
 	Field offset:Int
 
-	Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Int=0 )
+	Method Create:TFieldDecl( ident$,ty:TType,init:TExpr,attrs:Long=0 )
 		Self.ident=ident
 		Self.declTy=ty
 		Self.declInit=init
@@ -889,7 +895,7 @@ Type TAliasDecl Extends TDecl
 
 	Field decl:Object
 	
-	Method Create:TAliasDecl( ident$,decl:Object,attrs:Int=0 )
+	Method Create:TAliasDecl( ident$,decl:Object,attrs:Long=0 )
 		Self.ident=ident
 		Self.decl=decl
 		Self.attrs=attrs
@@ -1860,16 +1866,16 @@ Type TBlockDecl Extends TScopeDecl
 	End Method
 End Type
 
-Const FUNC_METHOD:Int=   $0001			'mutually exclusive with ctor
-Const FUNC_CTOR:Int=     $0002
-Const FUNC_PROPERTY:Int= $0004
-Const FUNC_DTOR:Int=     $0008
-Const FUNC_BUILTIN:Int = $0080
-Const FUNC_PTR:Int=      $0100
-Const FUNC_INIT:Int =    $0200
-Const FUNC_NESTED:Int =  $0400
-Const FUNC_OPERATOR:Int= $0800
-Const FUNC_FIELD:Int=    $1000
+Const FUNC_METHOD:Long=   $0001			'mutually exclusive with ctor
+Const FUNC_CTOR:Long=     $0002
+Const FUNC_PROPERTY:Long= $0004
+Const FUNC_DTOR:Long=     $0008
+Const FUNC_BUILTIN:Long = $0080
+Const FUNC_PTR:Long=      $0100
+Const FUNC_INIT:Long =    $0200
+Const FUNC_NESTED:Long =  $0400
+Const FUNC_OPERATOR:Long= $0800
+Const FUNC_FIELD:Long=    $1000
 
 'Fix! A func is NOT a block/scope!
 '
@@ -1895,7 +1901,7 @@ Type TFuncDecl Extends TBlockDecl
 	
 	Field equalsBuiltIn:Int = -1
 	
-	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Int )
+	Method CreateF:TFuncDecl( ident$,ty:TType,argDecls:TArgDecl[],attrs:Long )
 		Self.ident=ident
 		Self.retTypeExpr=ty
 		If argDecls
@@ -2465,7 +2471,7 @@ Type TClassDecl Extends TScopeDecl
 
 	'Global nullObjectClass:TClassDecl=New TNullDecl.Create( "{NULL}",Null,Null,Null,DECL_ABSTRACT|DECL_EXTERN )
 	
-	Method Create:TClassDecl( ident$,args:TTemplateArg[],superTy:TIdentType,impls:TIdentType[],attrs:Int )
+	Method Create:TClassDecl( ident$,args:TTemplateArg[],superTy:TIdentType,impls:TIdentType[],attrs:Long )
 		Self.ident=ident
 		Self.args=args
 		Self.superTy=superTy
@@ -3557,7 +3563,7 @@ Type TLoopLabelDecl Extends TDecl ' also used internally for Try constructs
 
 	Field realIdent:String
 
-	Method Create:TLoopLabelDecl( ident$, attrs:Int=0 )
+	Method Create:TLoopLabelDecl( ident$, attrs:Long=0 )
 		If Not ident.StartsWith("#") Then
 			Self.ident="#" + ident
 			Self.realIdent = ident
@@ -3583,7 +3589,7 @@ Type TDataLabelDecl Extends TDecl
 	Field realIdent:String
 	Field index:Int
 
-	Method Create:TDataLabelDecl( ident$, attrs:Int=0 )
+	Method Create:TDataLabelDecl( ident$, attrs:Long=0 )
 		If Not ident.StartsWith("#") Then
 			Self.ident="#" + ident
 			Self.realIdent = ident
@@ -3611,7 +3617,7 @@ Type TDefDataDecl Extends TDecl
 	Field label:TDataLabelDecl
 	Field data:TExpr[]
 
-	Method Create:TDefDataDecl(data:TExpr[], label:TDataLabelDecl = Null, attrs:Int=0 )
+	Method Create:TDefDataDecl(data:TExpr[], label:TDataLabelDecl = Null, attrs:Long=0 )
 		Self.data=data
 		Self.label=label
 		Self.attrs=attrs
@@ -3911,7 +3917,7 @@ Type TModuleDecl Extends TScopeDecl
 		Return "Module "+munged
 	End Method
 	
-	Method Create:TModuleDecl( ident$,munged$,filepath$,attrs:Int )
+	Method Create:TModuleDecl( ident$,munged$,filepath$,attrs:Long )
 		Self.ident=ident
 		Self.munged=munged
 		Self.filepath=filepath

+ 12 - 12
iparser.bmx

@@ -42,7 +42,7 @@ Type TIParser
 	Field _tokeSpace:Int
 	Field _tokerStack:TList=New TList'<TToker>
 
-	Method ParseModuleImport:Int(pmod:TModuleDecl, modpath:String, path:String, imp:String = Null, iData:String = Null, attrs:Int = 0, relPath:String = "", isFileImport:Int = 0)
+	Method ParseModuleImport:Int(pmod:TModuleDecl, modpath:String, path:String, imp:String = Null, iData:String = Null, attrs:Long = 0, relPath:String = "", isFileImport:Int = 0)
 
 		Const STATE_CLASS:Int = 1
 
@@ -477,7 +477,7 @@ Type TIParser
 						Exit
 					End If
 
-					Local a:Int
+					Local a:Long
 					Local ty:TType = ParseDeclType(a)
 
 					If CParse("(") Then
@@ -664,7 +664,7 @@ Type TIParser
 		
 	End Method
 
-	Method ParseClassDecl:TClassDecl( toke$,attrs:Int )
+	Method ParseClassDecl:TClassDecl( toke$,attrs:Long )
 		SetErr
 
 		'If toke Parse toke
@@ -710,9 +710,9 @@ Type TIParser
 		
 		'If classDecl.IsTemplateArg() Return classDecl
 
-		Local decl_attrs:Int=(attrs & DECL_EXTERN)
+		Local decl_attrs:Long=(attrs & DECL_EXTERN)
 		
-		Local method_attrs:Int=decl_attrs
+		Local method_attrs:Long=decl_attrs
 		If attrs & CLASS_INTERFACE method_attrs:|DECL_ABSTRACT
 
 		Repeat
@@ -748,7 +748,7 @@ Type TIParser
 				classDecl.InsertDecl decl
 
 			Case ".", "@", "~~" ' field			
-				Local d_attrs:Int = decl_attrs | DECL_FIELD
+				Local d_attrs:Long = decl_attrs | DECL_FIELD
 				If _toker._toke = "." Then
 					NextToke
 				Else
@@ -815,7 +815,7 @@ Type TIParser
 
 		Local id$=ParseIdent()
 		Local ty:TType
-		Local attrs:Int
+		Local attrs:Long
 
 		Parse( "\" )
 		ty=ParseDeclType(attrs, False)
@@ -979,14 +979,14 @@ Type TIParser
 		Return str
 	End Method
 
-	Method ParseFuncDecl:TFuncDecl( toke$,attrs:Int, returnType:TType = Null, classDecl:TClassDecl = Null )
+	Method ParseFuncDecl:TFuncDecl( toke$,attrs:Long, returnType:TType = Null, classDecl:TClassDecl = Null )
 		SetErr
 
 		'If toke Parse toke
 	
 		Local id$
 		Local ty:TType
-		Local meth:Int = attrs & FUNC_METHOD
+		Local meth:Long = attrs & FUNC_METHOD
 
 		If Not returnType Then		
 			If attrs & FUNC_METHOD
@@ -1278,7 +1278,7 @@ Type TIParser
 		
 	End Method
 	
-	Method ParseDecl:TDecl( toke$,attrs:Int )
+	Method ParseDecl:TDecl( toke$,attrs:Long )
 		SetErr
 		Local pos:Int, tokeType:Int
 		pos = _toker._tokePos
@@ -1525,7 +1525,7 @@ End Rem
 		Return isDef
 	End Method
 
-	Method ParseDeclType:TType(attrs:Int Var, fn:Int = False)
+	Method ParseDeclType:TType(attrs:Long Var, fn:Int = False)
 		Local ty:TType
 		Select _toker._toke
 		'Case "?"
@@ -1906,7 +1906,7 @@ End Rem
 		Return ParseIdentType()
 	End Method
 	
-	Method ApplyFunctionAttributes(classDecl:TClassDecl, attrs:Int)
+	Method ApplyFunctionAttributes(classDecl:TClassDecl, attrs:Long)
 		For Local decl:TFuncDecl = EachIn classDecl._decls
 			decl.attrs :| attrs
 		Next

+ 1 - 1
options.bmx

@@ -25,7 +25,7 @@ SuperStrict
 
 Import "base.configmap.bmx"
 
-Const version:String = "0.131"
+Const version:String = "0.132"
 
 Const BUILDTYPE_APP:Int = 0
 Const BUILDTYPE_MODULE:Int = 1

+ 35 - 24
parser.bmx

@@ -925,7 +925,7 @@ Type TParser Extends TGenProcessor
 		Return ty
 	End Method
 
-	Method ParseDeclType:TType(attr:Int = 0)
+	Method ParseDeclType:TType(attr:Long = 0)
 		Local ty:TType
 		Select _toke
 		Case "@"
@@ -2389,7 +2389,7 @@ End Rem
 		End If
 	End Method
 
-	Method ParseExternBlock(mdecl:TModuleDecl, attrs:Int)
+	Method ParseExternBlock(mdecl:TModuleDecl, attrs:Long)
 
 		NextToke
 
@@ -2412,6 +2412,8 @@ End Rem
 					mdecl.InsertDecls ParseDecls( _toke,attrs )
 				Case "global"
 					ParseDeclStmts(True, attrs, mdecl)
+				Case "threadedglobal"
+					ParseDeclStmts(True, attrs | DECL_THREADED, mdecl)
 				Case "struct"
 					mdecl.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
 				Case "type"
@@ -2439,7 +2441,7 @@ End Rem
 		Select _toke
 			Case ";","~n"
 				NextToke
-			Case "const","local","global"
+			Case "const","local","global","threadedglobal"
 				ParseDeclStmts
 			' nested function - needs to get added to the "module"
 			Case "function"
@@ -2557,7 +2559,7 @@ End Rem
 		End Select
 	End Method
 
-	Method ParseDecl:TDecl( toke$,attrs:Int )
+	Method ParseDecl:TDecl( toke$,attrs:Long )
 
 		SetErr
 
@@ -2621,7 +2623,7 @@ End Rem
 					ty=New TArrayType.Create( ty, ln.length,, attrs & DECL_STATIC > 0 )
 				End If
 			Else If toke <> "const"
-				If toke="global" Or toke="local" Then
+				If toke="global" Or toke="local" Or toke="threadedglobal" Then
 					init=New TConstExpr.Create( ty,"" )
 				End If
 			Else
@@ -2636,6 +2638,8 @@ End Rem
 		Select toke
 		Case "global"
 			decl=New TGlobalDecl.Create( id,ty,init,attrs )
+		Case "threadedglobal"
+			decl=New TGlobalDecl.Create( id,ty,init,attrs | DECL_THREADED )
 		Case "field"
 			decl=New TFieldDecl.Create( id,ty,init,attrs )
 
@@ -2704,7 +2708,7 @@ End Rem
 		Return decl
 	End Method
 
-	Method ParseDecls:TList( toke$,attrs:Int, isField:Int = False )
+	Method ParseDecls:TList( toke$,attrs:Long, isField:Int = False )
 		If toke Parse toke
 
 		If isField Then
@@ -2736,7 +2740,7 @@ End Rem
 		Forever
 	End Method
 
-	Method ParseDeclStmts(initOnly:Int = False, attrs:Int = 0, mdecl:TModuleDecl  = Null)
+	Method ParseDeclStmts(initOnly:Int = False, attrs:Long = 0, mdecl:TModuleDecl  = Null)
 		Local toke$=_toke
 		NextToke
 		Repeat
@@ -2878,7 +2882,7 @@ End Rem
 	End Method
 	
 	
-	Method ParseFuncDecl:TFuncDecl( toke$, attrs:Int, parent:TScopeDecl = Null )
+	Method ParseFuncDecl:TFuncDecl( toke$, attrs:Long, parent:TScopeDecl = Null )
 		SetErr
 
 		If toke Parse toke
@@ -2975,7 +2979,7 @@ End Rem
 			attrs :| (fdecl.attrs & DECL_API_FLAGS)
 		End If
 		
-		Local declaredAttrs:Int
+		Local declaredAttrs:Long
 		While True
 			If CParse( "nodebug" ) Then
 				If declaredAttrs & DECL_NODEBUG Then Err "Duplicate modifier 'NoDebug'"
@@ -3179,7 +3183,7 @@ End Rem
 		Return funcDecl
 	End Method
 	
-	Method ParseCallConvention:Int(callConvention:Int = DECL_API_DEFAULT)
+	Method ParseCallConvention:Long(callConvention:Long = DECL_API_DEFAULT)
 		If _tokeType <> TOKE_STRINGLIT Then
 			Return callConvention
 		End If
@@ -3221,7 +3225,7 @@ End Rem
 		If _toke<>")"
 			Local nargs:Int
 			Repeat
-				Local attrs:Int
+				Local attrs:Long
 				If CParse("staticarray") Then
 					attrs :| DECL_STATIC
 				End If
@@ -3317,7 +3321,7 @@ End Rem
 		
 	End Method
 
-	Method ParseClassDecl:TClassDecl( toke$,attrs:Int, templateDets:TTemplateDets = Null )
+	Method ParseClassDecl:TClassDecl( toke$,attrs:Long, templateDets:TTemplateDets = Null )
 		SetErr
 
 		Local calculatedStartLine:Int = _toker.Line()
@@ -3536,11 +3540,11 @@ End Rem
 
 		'If classDecl.IsTemplateArg() Return classDecl
 
-		Local decl_attrs:Int=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
+		Local decl_attrs:Long=(attrs & DECL_EXTERN) | (attrs & DECL_NODEBUG) | (attrs & DECL_API_STDCALL)
 
 		Repeat
-			Local method_attrs:Int=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
-			Local abst_attrs:Int = 0
+			Local method_attrs:Long=decl_attrs|FUNC_METHOD | (attrs & DECL_NODEBUG)
+			Local abst_attrs:Long = 0
 			If attrs & CLASS_INTERFACE abst_attrs:|DECL_ABSTRACT
 		
 			SkipEols
@@ -3596,7 +3600,12 @@ End Rem
 				NextToke
 				decl_attrs:& ~DECL_PRIVATE
 				decl_attrs:& ~DECL_PROTECTED
-			Case "const","global","field"
+			Case "const","global","field","threadedglobal"
+				Local extra_attrs:Long
+				If _toke = "threadedglobal" Then
+					extra_attrs = DECL_THREADED
+				End If
+			
 				If attrs & DECL_EXTERN Then
 					If (attrs & CLASS_INTERFACE) Then
 						Err "Extern Interfaces can only contain methods."
@@ -3608,11 +3617,11 @@ End Rem
 				If (attrs & CLASS_INTERFACE) And _toke<>"const"
 					Err "Interfaces can only contain constants and methods."
 				EndIf
-				If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global"
+				If (attrs & CLASS_STRUCT) And _toke<>"field" And _toke<>"global" And _toke<>"threadedglobal"
 					Err "Structs can only contain fields."
 				EndIf
 				
-				classDecl.InsertDecls ParseDecls( _toke,decl_attrs, _toke = "field")
+				classDecl.InsertDecls ParseDecls( _toke,decl_attrs | extra_attrs, _toke = "field")
 			Case "method"
 				If (attrs & CLASS_STRUCT) And (attrs & DECL_EXTERN) Then
 					Err "Structs can only contain fields."
@@ -3665,7 +3674,7 @@ End Rem
 		NextToke
 	End Method
 
-	Method ParseModuleDecl:String( toke$,attrs:Int )
+	Method ParseModuleDecl:String( toke$,attrs:Long )
 		NextToke
 
 		' namespace . module
@@ -3745,7 +3754,7 @@ End Rem
 
 	End Method
 
-	Method ImportAllModules(attrs:Int)
+	Method ImportAllModules(attrs:Long)
 
 		' get all brl and pub modules
 		Local mods:TList = EnumModules("brl")
@@ -3757,7 +3766,7 @@ End Rem
 
 	End Method
 	
-	Method ImportModule( modpath$,attrs:Int )
+	Method ImportModule( modpath$,attrs:Long )
 		SetErr
 		
 		modpath = modpath.ToLower()
@@ -3999,7 +4008,7 @@ End Rem
 		Return dets
 	End Method
 
-	Method ParseCurrentFile:Int(path:String, attrs:Int)
+	Method ParseCurrentFile:Long(path:String, attrs:Long)
 
 		LoadExternCasts(path)
 
@@ -4022,6 +4031,8 @@ End Rem
 				_module.InsertDecls ParseDecls( _toke,attrs )
 			Case "global"
 				ParseDeclStmts(True, attrs, _module)
+			Case "threadedglobal"
+				ParseDeclStmts(True, attrs | DECL_THREADED, _module)
 			Case "struct"
 				_module.InsertDecl ParseClassDecl( _toke,attrs | CLASS_STRUCT )
 			Case "type"
@@ -4117,7 +4128,7 @@ End Rem
 
 		SkipEols
 
-		Local mattrs:Int
+		Local mattrs:Long
 		'If CParse( "strict" ) mattrs:|MODULE_STRICT
 		'If CParse( "superstrict" ) mattrs:|MODULE_SUPERSTRICT
 
@@ -4194,7 +4205,7 @@ End Rem
 		End If
 
 
-		Local attrs:Int
+		Local attrs:Long
 
 		While _toke
 			SetErr

+ 1 - 1
toker.bmx

@@ -51,7 +51,7 @@ Type TToker
 		"next,return,alias,rem,endrem,throw,assert,try,catch,finally,nodebug,incbin,endselect,endmethod," + ..
 		"endfunction,endtype,endextern,endtry,endwhile,pi,release,defdata,readdata,restoredata,interface," + ..
 		"endinterface,implements,size_t,uint,ulong,struct,endstruct,operator,where,readonly,export,override," + ..
-		"enum,endenum,stackalloc,inline,fieldoffset,staticarray"
+		"enum,endenum,stackalloc,inline,fieldoffset,staticarray,threadedglobal"
 	Global _keywords:TMap
 
 	Field _path$