c1/DragonFly__C1Compiler.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 12 Feb 2016 11:51:14 +0000
changeset 17 54798ae989cc
child 18 81ed8ce0852f
child 19 51a3540a2a10
permissions -rw-r--r--
Initial work on LLVM-based C1 compiler

"{ Package: 'jv:dragonfly/c1' }"

"{ NameSpace: DragonFly }"

Object subclass:#C1Compiler
	instanceVariableNames:'method module function asm prologue epilogue'
	classVariableNames:'SelectorSpecialCharMappingTable'
	poolDictionaries:'DragonFly::C1LLVMMTypes LLVMIntPredicate VMData VMOffsets'
	category:'DragonFly-C1'
!

!C1Compiler class methodsFor:'class initialization'!

initialize
    "Invoked at system start or when the class is dynamically loaded."

    "/ please change as required (and remove this comment)

    SelectorSpecialCharMappingTable := Dictionary withKeysAndValues:
                #($+ 'pl'
                  $- 'mi'
                  $* 'mu'
                  $/ 'di'
                  $, 'co'
                  $@ 'at'
                  $< 'le'
                  $> 'gr'
                  $= 'eq'
                  $~ 'ne'
                  $| 'pi'
                  $\ 'mo'
                  $& 'am').

    "Created: / 09-02-2016 / 08:43:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!C1Compiler class methodsFor:'compilation'!

compile: method
    ^ self new compile: method

    "Created: / 09-02-2016 / 08:47:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!C1Compiler class methodsFor:'utilities'!

functionNameForClass: class selector: selector      
    "For given class name and selector, returns the name 
     used by LLVM"

    ^ String streamContents:[ :s|
        s nextPutAll: '__M_D_'.
        s nextPutAll: (class name copyReplaceAll: $: with: $_).
        s nextPut: $_.
        selector isBinarySelector ifTrue:[ 
            selector do:[:c |     
                s nextPutAll: (SelectorSpecialCharMappingTable at: c)
            ].
        ] ifFalse:[ 
            selector do:[:c |  
                c isAlphaNumeric ifTrue:[ 
                    s nextPut: c 
                ] ifFalse:[
                    s nextPut: $_.
                    c == $: ifFalse:[ 
                        c codePoint printOn: s.
                    ]
                ].
            ]
        ].
    ].

    "
    C1Compiler functionNameForClass: C1Compiler selector: #functionNameForClass:selector: 
    C1Compiler functionNameForClass: SmallInteger selector: #+
    C1Compiler functionNameForClass: Object selector: #~=
    C1Compiler functionNameForClass: JavaVM selector: #_ALOAD:

    "

    "Created: / 09-02-2016 / 08:44:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!C1Compiler methodsFor:'compilation'!

compile: aMethod
    | 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.

    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>"
! !

!C1Compiler methodsFor:'private'!

epilogue
    self halt.

    "Created: / 15-04-2016 / 23:38:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

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 ).
    classCheckFailedBlock := function addBasicBlockNamed: 'prologue.class-check-failed'. 
    classCheckPassedBlock := function addBasicBlockNamed: 'prologue.class-check-passed'.
    classCheck := asm icmp: (asm ptr: classOfReceiver toInt: LLVMType intptr)
                         _: (asm ptr: classInILC toInt: LLVMType intptr)
                      cond: LLVMIntEQ.
    asm if: classCheck then: classCheckPassedBlock else: classCheckFailedBlock.

    "/ Class check failed, call _SENDX()"
    asm block: classCheckFailedBlock.


    "/ Classes match, continue.
    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>"
! !

!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>"
!

fetchClassOf:obj 
    ^ asm 
        select:(self isSmallIntegerObject:obj)
        then: self fetchClassSmallInteger
        else: (asm load: (asm gep:obj at: { 0 . TyInstanceIndexClass })).

    "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>"
!

fetchClassSmallInteger
    | addr |

    addr := asm int: (LLVMConstant uintptr: ADDR_SmallInteger) toPtr: TyOBJ pointer.
    ^ asm load: addr.

    "Created: / 12-02-2016 / 11:54:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!C1Compiler methodsFor:'private-testing'!

isSmallIntegerObject: value
    self assert: value type = TyOBJ.
    ^ asm icmp: (asm and: (asm ptr: value toInt: LLVMType intptr) _: (LLVMConstant uintptr: 1))
             _: (LLVMConstant uintptr: 1)
          cond: LLVMIntEQ

    "Created: / 09-02-2016 / 17:30:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-02-2016 / 11:55:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !


C1Compiler initialize!