C1: Added C1Compiler #prepare/#finish
authorJan Vrany <jan.vrany@fit.cvut.cz>
Thu, 21 Apr 2016 09:58:19 +0100
changeset 19 51a3540a2a10
parent 17 54798ae989cc
child 20 7f2660be9066
C1: Added C1Compiler #prepare/#finish #prepare prepares everything for LLVM IR construction, but does not generate any IR instructions (not even prologue). #finish allocates a code object, generates a machine code and update method's code pointer. As a side effect, this allows for easier testing of building blocks (such as #loadClassOf: and so on)
CompiledCodeObject.st
bmake.bat
c1/DragonFly__C1Compiler.st
c1/DragonFly__C1CompilerTests.st
c1/bmake.bat
c1/jv_dragonfly_c1.st
c1/mingwmake.bat
c1/vcmake.bat
mingwmake.bat
udis86sx/bmake.bat
udis86sx/mingwmake.bat
udis86sx/vcmake.bat
vcmake.bat
--- a/CompiledCodeObject.st	Fri Feb 12 11:51:14 2016 +0000
+++ b/CompiledCodeObject.st	Thu Apr 21 09:58:19 2016 +0100
@@ -315,7 +315,7 @@
     <inspector2Tab>   
 
     self sections do:[:section | 
-        section isTextSection ifTrue:[ 
+        section format == SectionFormatText ifTrue:[ 
             | tab |
 
             tab := section inspector2TabAssembly.
@@ -328,7 +328,7 @@
     ^ nil
 
     "Created: / 11-12-2015 / 12:04:47 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 11-12-2015 / 14:11:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 15:39:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !CompiledCodeObject methodsFor:'private'!
--- a/bmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/bmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -10,6 +10,7 @@
 
 make.exe -N -f bc.mak  %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/c1/DragonFly__C1Compiler.st	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/DragonFly__C1Compiler.st	Thu Apr 21 09:58:19 2016 +0100
@@ -9,6 +9,7 @@
 	category:'DragonFly-C1'
 !
 
+
 !C1Compiler class methodsFor:'class initialization'!
 
 initialize
@@ -81,21 +82,59 @@
     "Created: / 09-02-2016 / 08:44:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!C1Compiler methodsFor:'accessing'!
+
+method
+    ^ method
+!
+
+method:aMethod
+    method := aMethod.
+! !
+
 !C1Compiler methodsFor:'compilation'!
 
 compile: aMethod
+    self method: aMethod.
+    self prepare.
+    self prologue.
+
+    self epilogue.
+    self finish.
+
+    "Created: / 09-02-2016 / 08:52:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 09:18:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+finish
+    "Finish the compilation, i.e., generate machine code
+     and update method's code pointer"
+    | opts mm object jit |
+
+    object := CompiledCodeObject forCompiledCode: method text: 0 literals: 0 ilcs: 0.
+    mm := C1LLVMMCJITMemoryManager for: object.
+    opts := LLVMMCJITCompilerOptions new.
+    opts MCJMM: mm.
+    jit := LLVMExecutionEngine newForModule: module options: opts.
+    method code: (jit addressOfFunction: function).
+
+    "Created: / 21-04-2016 / 09:19:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+prepare
     | name |
-    method := aMethod.
     name := self class functionNameForClass: method mclass ? UndefinedObject selector: method selector ? '<unbound>'.
     module := LLVMModule newWithName: name.
     function := module addFunctionNamed: name type: (TyOBJFUNCs at: method numArgs + 1).
-    asm := LLVMIRBuilder new.
-    self prologue.
+    (function parameterAt: OBJFUNCArgIndexReceiver) name: 'zelf'.
+    (function parameterAt: OBJFUNCArgIndexSelector) name: 'selector'.
+    (function parameterAt: OBJFUNCArgIndexSearchClass) name: 'searchClass'.
+    (function parameterAt: OBJFUNCArgIndexILC) name: 'pilc'.
+    1 to: method numArgs do:[:i | (function parameterAt: OBJFUNCArgIndexArgBase + i) name: 'arg' , i printString ].
+    asm := function builder.
 
-    self epilogue.
-
-    "Created: / 09-02-2016 / 08:52:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 15-04-2016 / 23:38:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Created: / 21-04-2016 / 09:17:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 16:52:16 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !C1Compiler methodsFor:'private'!
@@ -109,9 +148,9 @@
 prologue
     | classOfReceiver classInILC classCheckFailedBlock classCheckPassedBlock classCheck |
     prologue := function addBasicBlockNamed: 'prologue'.
-    asm block: prologue.
-    classOfReceiver := self fetchClassOf: (function parameterAt: OBJFUNCArgIndexReceiver ).
-    classInILC := self fetchClassFromILC: (function parameterAt: OBJFUNCArgIndexILC ).
+    asm continue: prologue.
+    classOfReceiver := self loadClassOf:(function parameterAt:OBJFUNCArgIndexReceiver).
+    classInILC := self loadClassFromILC:(function parameterAt:OBJFUNCArgIndexILC).
     classCheckFailedBlock := function addBasicBlockNamed: 'prologue.class-check-failed'. 
     classCheckPassedBlock := function addBasicBlockNamed: 'prologue.class-check-passed'.
     classCheck := asm icmp: (asm ptr: classOfReceiver toInt: LLVMType intptr)
@@ -127,37 +166,49 @@
     asm block: classCheckPassedBlock.
 
     "Created: / 09-02-2016 / 17:07:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 15-04-2016 / 23:45:46 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 12:05:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !C1Compiler methodsFor:'private-fetch / store'!
 
-fetchClassFromILC: pIlc
-    self assert: pIlc type = TyInlineCachePtr.
-
-    ^ asm load: (asm gep: pIlc at: { 0. TyInlineCacheIndexClass })
-
-    "Created: / 12-02-2016 / 13:19:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 15-04-2016 / 23:18:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+loadClassFromILC:pIlc 
+    self assert:pIlc type = TyInlineCachePtr.
+    ^ asm load:(asm gep:pIlc at:{ 0 . TyInlineCacheIndexClass })
+             "Created: / 12-02-2016 / 13:19:19 / Jan Vrany <jan.vrany@fit.cvut.cz>" "Modified: / 15-04-2016 / 23:18:52 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-fetchClassOf:obj 
-    ^ asm 
-        select:(self isSmallIntegerObject:obj)
-        then: self fetchClassSmallInteger
-        else: (asm load: (asm gep:obj at: { 0 . TyInstanceIndexClass })).
+loadClassOf:obj
+    | classes |
+
+    classes := Array new: 2.
+    asm if: (self isSmallIntegerObject:obj) then: [
+        classes at: 1 put: self loadClassSmallInteger.
+    ] else:[  
+        classes at: 2 put: (asm load:(asm gep:obj at:{ 0 . TyInstanceFieldIndexClass })).
+    ].
+    ^ asm phi: classes
 
     "Created: / 09-02-2016 / 17:25:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 15-04-2016 / 23:19:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 22-04-2016 / 15:11:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
-fetchClassSmallInteger
+loadClassSmallInteger
     | addr |
 
-    addr := asm int: (LLVMConstant uintptr: ADDR_SmallInteger) toPtr: TyOBJ pointer.
-    ^ asm load: addr.
+    addr := asm 
+                int:(LLVMConstant uintptr:ADDR_SmallInteger)
+                toPtr:TyOBJ pointer
+                as:'ADDR_SmallInteger'.
+    ^ asm load:addr as: 'SmallInteger'.
 
     "Created: / 12-02-2016 / 11:54:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 17:03:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+loadNil
+    ^ asm int:(LLVMConstant uintptr:0) toPtr:TyOBJ.
+
+    "Created: / 21-04-2016 / 13:59:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !C1Compiler methodsFor:'private-testing'!
@@ -172,5 +223,12 @@
     "Modified: / 12-02-2016 / 11:55:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!C1Compiler class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
 
 C1Compiler initialize!
--- a/c1/DragonFly__C1CompilerTests.st	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/DragonFly__C1CompilerTests.st	Thu Apr 21 09:58:19 2016 +0100
@@ -9,55 +9,8 @@
 	category:'DragonFly-C1-Tests'
 !
 
-!C1CompilerTests methodsFor:'tests'!
 
-test_fetchClassOf
-    | compiler module function asm jit test |
-
-    compiler := C1Compiler new.
-    module := LLVMModule newWithName: testSelector.
-    function := module addFunctionNamed: 'test'
-                                   type: (LLVMType function: { TyOBJ } returning: TyOBJ).
-    asm := function builder.
-    compiler 
-        instVarNamed: #module put: module;
-        instVarNamed: #function put: function;
-        instVarNamed: #asm put: asm.
-
-    asm ret: (compiler fetchClassOf: (function parameterAt: 1)).
-
-    jit := LLVMExecutionEngine newForModule: module.  
-    test := jit externalOfFunction: function. 
-
-    self assert: (test callOWith: 1) == SmallInteger.
-    self assert: (test callOWith: self) == self class.
-    self assert: (test callOWith: 1.0) == 1.0 class.
-
-    "Created: / 12-02-2016 / 12:27:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
-
-test_fetchClassSmallInteger
-    | compiler module function asm jit test |
-
-    compiler := C1Compiler new.
-    module := LLVMModule newWithName: testSelector.
-    function := module addFunctionNamed: 'test'
-                                   type: (LLVMType function: { } returning: TyOBJ).
-    asm := function builder.
-    compiler 
-        instVarNamed: #module put: module;
-        instVarNamed: #function put: function;
-        instVarNamed: #asm put: asm.
-
-    asm ret: (compiler fetchClassSmallInteger).
-
-    jit := LLVMExecutionEngine newForModule: module.  
-    test := jit externalOfFunction: function. 
-
-    self assert: (test callO) == SmallInteger.
-
-    "Created: / 12-02-2016 / 12:26:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-!
+!C1CompilerTests methodsFor:'tests - building blocks'!
 
 test_isSmallIntegerObject
     | compiler module function asm jit test |
@@ -81,5 +34,89 @@
     self assert: (test callWith: self) == 0.
 
     "Created: / 12-02-2016 / 12:17:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_loadClassOf
+    | method compiler asm obj |
+
+    method := Method new.
+    method numberOfArgs: 2.
+    method numberOfVars: 0.
+    method stackSize: 0.
+
+    compiler := C1Compiler new.
+    compiler method: method.
+    compiler prepare.
+
+    asm := compiler instVarNamed: #asm.
+    obj := (compiler instVarNamed: #function) parameterAt: OBJFUNCArgIndexArg1.
+    asm ret: (compiler loadClassOf: obj).
+
+    compiler finish.
+
+    self assert: method code notNil.
+    self assert: (method valueWithReceiver:nil arguments: { 1.0  . 2 }) == Double.
+    self assert: (method valueWithReceiver:nil arguments: { self . 2 }) == self class.
+    self assert: (method valueWithReceiver:nil arguments: { 1 . 2 }) == SmallInteger
+
+    "Created: / 12-02-2016 / 12:27:26 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 22-04-2016 / 09:57:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+test_loadClassSmallInteger
+    | method compiler asm |
+
+    method := Method new.
+    method numberOfArgs: 2.
+    method numberOfVars: 0.
+    method stackSize: 0.
+
+    compiler := C1Compiler new.
+    compiler method: method.
+    compiler prepare.
+
+    asm := compiler instVarNamed: #asm.
+    asm ret: (compiler loadClassSmallInteger).
+
+    compiler finish.
+
+    self assert: method code notNil.
+    self assert: (method valueWithReceiver:nil arguments: #(1 2)) == SmallInteger
+
+    "Created: / 12-02-2016 / 12:26:14 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 21-04-2016 / 09:23:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified (format): / 21-04-2016 / 14:02:06 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!C1CompilerTests methodsFor:'tests - codegen'!
+
+test_codegen
+    | method compiler asm |
+
+    method := Method new.
+    method numberOfArgs: 2.
+    method numberOfVars: 0.
+    method stackSize: 0.
+
+    compiler := C1Compiler new.
+    compiler method: method.
+    compiler prepare.
+
+    asm := compiler instVarNamed: #asm.
+    asm ret: (asm int: (LLVMConstant uintptr: 0) toPtr: TyOBJ).  
+
+    compiler finish.
+
+    self assert: method code notNil.
+    self assert: (method valueWithReceiver:nil arguments: #(1 2)) == nil
+
+    "Created: / 21-04-2016 / 13:48:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!C1CompilerTests class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/c1/bmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/bmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -10,6 +10,7 @@
 
 make.exe -N -f bc.mak  %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/c1/jv_dragonfly_c1.st	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/jv_dragonfly_c1.st	Thu Apr 21 09:58:19 2016 +0100
@@ -48,7 +48,7 @@
 
     ^ #(
     )
-!
+! !
 
 !jv_dragonfly_c1 class methodsFor:'description - contents'!
 
@@ -76,4 +76,9 @@
     )
 ! !
 
+!jv_dragonfly_c1 class methodsFor:'documentation'!
 
+version_HG
+    ^ '$Changeset: <not expanded> $'
+! !
+
--- a/c1/mingwmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/mingwmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -13,6 +13,7 @@
 @popd
 make.exe -N -f bc.mak %DEFINES% %USEMINGW_ARG% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/c1/vcmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/c1/vcmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -17,6 +17,7 @@
 
 make.exe -N -f bc.mak -DUSEVC=1 %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/mingwmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/mingwmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -13,6 +13,7 @@
 @popd
 make.exe -N -f bc.mak %DEFINES% %USEMINGW_ARG% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/udis86sx/bmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/udis86sx/bmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -10,6 +10,7 @@
 
 make.exe -N -f bc.mak  %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/udis86sx/mingwmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/udis86sx/mingwmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -13,6 +13,7 @@
 @popd
 make.exe -N -f bc.mak %DEFINES% %USEMINGW_ARG% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/udis86sx/vcmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/udis86sx/vcmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -17,6 +17,7 @@
 
 make.exe -N -f bc.mak -DUSEVC=1 %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0
--- a/vcmake.bat	Fri Feb 12 11:51:14 2016 +0000
+++ b/vcmake.bat	Thu Apr 21 09:58:19 2016 +0100
@@ -17,6 +17,7 @@
 
 make.exe -N -f bc.mak -DUSEVC=1 %DEFINES% %*
 
+@IF "%1" EQU "test" exit /b 0
 @IF "%1" EQU "exe" exit /b 0
 @IF "%1" EQU "setup" exit /b 0
 @IF "%1" EQU "pluginSetup" exit /b 0