Tests refactored to be actually a testcase. Introduced LLVMConstant class
as a factory for LLVM constant values (such as integer or string constants)
"
Copyright (C) 2015-now Jan Vrany
This code is not an open-source (yet). You may use this code
for your own experiments and projects, given that:
* all modification to the code will be sent to the
original author for inclusion in future releases
* this is not used in any commercial software
This license is provisional and may (will) change in
a future.
"
"{ Package: 'jv:llvm_s' }"
"{ NameSpace: Smalltalk }"
TestCase subclass:#LLVMExamples
instanceVariableNames:''
classVariableNames:''
poolDictionaries:''
category:'LLVM-S-Core-Examples'
!
!LLVMExamples class methodsFor:'documentation'!
copyright
"
Copyright (C) 2015-now Jan Vrany
This code is not an open-source (yet). You may use this code
for your own experiments and projects, given that:
* all modification to the code will be sent to the
original author for inclusion in future releases
* this is not used in any commercial software
This license is provisional and may (will) change in
a future.
"
! !
!LLVMExamples class methodsFor:'accessing'!
isTestSelector:aSelector
^ (super isTestSelector:aSelector) or:[ aSelector startsWith: 'example' ]
"Created: / 03-08-2015 / 09:25:22 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!LLVMExamples methodsFor:'examples'!
example1_sum
"
Creates a simple function taking two arguments (as intptr_t) and returning
their sum (as intptr_t).
"
| module functionType function functionEntry asm jit externalFunction |
"/ 1) create a module to which the function would belong. A module is
"/ a set of functions and globals that are compiled at once by the MCJIT. Once
"/ module is compiled, no more methods or clobals can be added.
module := LLVMModule newWithName: testSelector.
"/ 2) Define a function within the module with type (intptr_t, intptr_t) -> intptr_t
functionType := LLVMType function: { LLVMType intptr . LLVMType intptr } returning: LLVMType intptr.
function := module addFunctionNamed: 'sum' type: functionType.
"/ 3) Generate function code. LLVM IR does not work with
"/ labels / jumps to labels but rather the user is responsible
"/ for creating basic blocks and adding them to the function.
"/ Hence, create a basic block named 'entry'
functionEntry := function addBasicBlockNamed: 'entry'.
"/ 4) To emit LLVM IR, create an IR builder and position it
"/ to the end of just created basic block.
asm := LLVMBuilder new.
asm positionAtEnd: functionEntry.
asm ret: (asm add: (function parameterAt: 1) and: (function parameterAt: 2)).
"/ Now, the module should look like
self assert: (module dumpString =
'; ModuleID = ''example1_sum''
define i64 @sum(i64, i64) {
entry:
%2 = add i64 %0, %1
ret i64 %2
}
').
"/ 5) To compile a function (strictly speaking, whole module) at runtime,
"/ create a jit object (called ExecutionEngine in LLVM)
jit := LLVMExecutionEngine newForModule: module.
"/ 6) Finally, obtain a reference to the function. This cause
"/ the module to be closed and compiled to machine code.
externalFunction := jit externalOfFunction: function.
self assert: (externalFunction callWith: 3 with: 4) == 7
"
LLVMExamples example1_sum
"
"Created: / 17-07-2015 / 11:47:11 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 03-08-2015 / 10:29:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
example2_function_call
"
Creates a module with two functions, @sum and @sum_caller. The latter
calls the former.
"
| module calleeFunctionType calleeFunction calleFunctionEntry
callerFunctionType callerFunction callerFunctionEntry
asm jit externalFunction |
module := LLVMModule newWithName: testSelector.
calleeFunctionType := LLVMType function: { LLVMType intptr . LLVMType intptr } returning: LLVMType intptr.
calleeFunction := module addFunctionNamed: 'sum' type: calleeFunctionType.
calleFunctionEntry := calleeFunction addBasicBlockNamed: 'entry'.
asm := LLVMBuilder new.
asm positionAtEnd: calleFunctionEntry.
asm ret: (asm add: (calleeFunction parameterAt: 1) and: (calleeFunction parameterAt: 2)).
callerFunctionType := LLVMType function: { LLVMType intptr . LLVMType intptr } returning: LLVMType intptr.
callerFunction := module addFunctionNamed: 'sum_caller' type: callerFunctionType.
callerFunctionEntry := callerFunction addBasicBlockNamed: 'entry'.
asm := LLVMBuilder new.
asm positionAtEnd: callerFunctionEntry.
asm ret: (asm call: calleeFunction with: (callerFunction parameterAt: 1) with: (callerFunction parameterAt: 2)).
self assert: (module dumpString =
'; ModuleID = ''example2_function_call''
define i64 @sum(i64, i64) {
entry:
%2 = add i64 %0, %1
ret i64 %2
}
define i64 @sum_caller(i64, i64) {
entry:
%2 = call i64 @sum(i64 %0, i64 %1)
ret i64 %2
}
').
jit := LLVMExecutionEngine newForModule: module.
externalFunction := jit externalOfFunction: callerFunction.
self assert: (externalFunction callWith: 3 with: 4) == 7.
"
LLVMExamples example2_function_call
"
"Created: / 17-07-2015 / 12:45:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 03-08-2015 / 10:29:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
example3_hello_world
"
Creates a function @main() which calls @printf() to print
a famous 'Hello World!!' message on stdout
"
| module printfFunctionType printfFunction
helloWorldString
mainFunctionType mainFunction mainFunctionEntry
asm jit externalFunction |
module := LLVMModule newWithName: testSelector.
printfFunctionType := LLVMType function: #() returning: LLVMType int32.
printfFunction := module addFunctionNamed: 'printf' type: printfFunctionType.
helloWorldString := module addGlobalNamed: '.str' value: (LLVMConstant string: 'Hello World!!\n').
mainFunctionType := LLVMType function: #() returning: LLVMType intptr.
mainFunction := module addFunctionNamed: 'main' type: mainFunctionType.
mainFunctionEntry := mainFunction addBasicBlockNamed: 'entry'.
asm := LLVMBuilder new.
asm positionAtEnd: mainFunctionEntry.
asm call: printfFunction with: helloWorldString.
asm ret: (LLVMConstant sint32: 0).
jit := LLVMExecutionEngine newForModule: module.
externalFunction := jit externalOfFunction: mainFunction.
externalFunction call.
Stdout flush
"
LLVMExamples example3_hello_world
"
"Created: / 03-08-2015 / 10:28:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 03-08-2015 / 18:00:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !