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)
--- 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