LLVMExamples.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Thu, 11 Aug 2016 09:12:17 +0100
changeset 73 466c492b0062
parent 71 ab03b0a6d037
child 76 a1cd10a34b21
permissions -rw-r--r--
Oops, fixed examples after a rename #store:_: to #store:at:

"
    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:'LLVMIntPredicate LLVMDWARFEncoding LLVMDWARFLamguage'
	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 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.

    "/ 2) To emit LLVM IR, get an IR builder for the function.
    "/    The LLVMFunction>>builder returns a builder on
    "/    function's entry point (basic block, strictly speaking)
    asm := function builder.
    asm ret: (asm add:(function parameterAt:1) _:(function parameterAt:2)).
    "/ Now, the module should look like
    self assert: (module dumpString =
'; ModuleID = ''example1_sum''
source_filename = "example1_sum"

define i64 @sum(i64, i64) {
entry:
  %2 = add i64 %0, %1
  ret i64 %2
}
').


    "/ 3) To compile a function (strictly speaking, whole module) at runtime,
    "/    create a jit object (called ExecutionEngine in LLVM)
    jit := LLVMExecutionEngine newForModule: module.

    "/ 4) 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: / 11-08-2016 / 09:06:09 / 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 callerFunctionType callerFunction asm jit externalFunction |

    module := LLVMModule newWithName: testSelector.

    calleeFunctionType := LLVMType function: { LLVMType intptr . LLVMType intptr } returning: LLVMType intptr.
    calleeFunction := module addFunctionNamed: 'sum' type: calleeFunctionType.

    asm := calleeFunction builder.
    asm ret: (asm add:(calleeFunction parameterAt:1) _:(calleeFunction parameterAt:2)).

    callerFunctionType := LLVMType function: { LLVMType intptr . LLVMType intptr } returning: LLVMType intptr.
    callerFunction := module addFunctionNamed: 'sum_caller' type: callerFunctionType.

    asm := callerFunction builder.
    asm ret: (asm call: calleeFunction _: { (callerFunction parameterAt: 1) . (callerFunction parameterAt: 2) }).
    self assert: (module dumpString = 
'; ModuleID = ''example2_function_call''
source_filename = "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: / 11-08-2016 / 09:06:29 / 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 
     asm jit externalFunction |

    module := LLVMModule newWithName: testSelector.

    printfFunctionType := LLVMType function: { LLVMType char pointer } varargs: true returning: LLVMType int32.
    printfFunction := module addFunctionNamed: 'printf' type: printfFunctionType.

    helloWorldString := module addGlobalNamed: '.str' value: (LLVMConstant string: 'Hello World!!' , Character lf).

    mainFunctionType := LLVMType function: #() returning: LLVMType int32.
    mainFunction := module addFunctionNamed: 'main' type: mainFunctionType.

    asm := mainFunction builder.
    asm call: printfFunction _: { asm gep: helloWorldString at: #(0 0) }.
    asm ret: (LLVMConstant sint32: 0).
    "
    module writeBitcodeToFile: '/tmp/main.bc'
    "    
    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: / 10-08-2015 / 18:58:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example4_cond
    "
    Creates a function @even(intpr) which returns
    1 if the parameter is even or 0 if not.
    "    

    | module 
     functionType function asm isOdd ifOdd ifEven jit externalFunction |

    module := LLVMModule newWithName: testSelector.

    functionType := LLVMType function: { LLVMType intptr } returning: LLVMType intptr.
    function := module addFunctionNamed: 'even' type: functionType.

    asm := function builder.
    isOdd := asm icmp: (asm and: (function parameterAt: 1) _: (LLVMConstant uintptr: 1)) _: (LLVMConstant uintptr: 1) cond: LLVMIntEQ.
    ifOdd := function addBasicBlock.
    ifOdd builder
        ret: (LLVMConstant uintptr: 0).
    ifEven := function addBasicBlock.
    ifEven builder
        ret: (LLVMConstant uintptr: 1).
    asm if: isOdd then: ifOdd else: ifEven.    

    jit := LLVMExecutionEngine newForModule: module.
    externalFunction := jit externalOfFunction: function.

    self assert: (externalFunction callWith: 10) == 1.
    self assert: (externalFunction callWith: 11) == 0.

    "
    LLVMExamples example3_cond
    "

    "Created: / 08-08-2015 / 04:16:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example4_cond_easy
    "
    Creates a function @even(intpr) which returns
    1 if the parameter is even or 0 if not.

    This demonstrate usage of blocks with
    LLVMIRBuilder>>if:then:else: which is easier to use
    than fiddling about basic blocks manually.
    "    

    | module 
     functionType function asm isOdd jit externalFunction |

    module := LLVMModule newWithName: testSelector.

    functionType := LLVMType function: { LLVMType intptr } returning: LLVMType intptr.
    function := module addFunctionNamed: 'even' type: functionType.

    asm := function builder.
    isOdd := asm icmp: (asm and: (function parameterAt: 1) _: (LLVMConstant uintptr: 1)) _: (LLVMConstant uintptr: 1) cond: LLVMIntEQ.
    asm if: isOdd then: [ 
        asm ret: (LLVMConstant uintptr: 0).
    ] else: [ 
        asm ret: (LLVMConstant uintptr: 1).
    ].

    jit := LLVMExecutionEngine newForModule: module.
    externalFunction := jit externalOfFunction: function.

    self assert: (externalFunction callWith: 10) == 1.
    self assert: (externalFunction callWith: 11) == 0.

    "
    LLVMExamples example3_cond
    "

    "Created: / 22-04-2016 / 10:22:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example5_factorial
    "A simple factorial using iterative algorithm.
     No overflow or negative value checks"
    
    | module functionType function asm  
    "Variables" result  i  
    "Blocks" entry loop loopBody exit jit externalFunction |

    module := LLVMModule newWithName:testSelector.
    functionType := LLVMType function:{ LLVMType intptr } returning:LLVMType intptr.
    function := module addFunctionNamed:'factorial' type:functionType.
    asm := LLVMIRBuilder new.
    entry := function entry.
    loop := function addBasicBlockNamed:'loop'.
    loopBody := function addBasicBlockNamed:'loopBody'.
    exit := function addBasicBlockNamed:'exit'.
     
    "/ Generate function setup
    "/ 
    "/ 03   function f(v) {
    "/ 04    var result;
    "/ 05    var i;
    "/ 06    result = 0;
    "/ 07    i := v;
    
    asm block:entry.
    result := asm alloca:LLVMType intptr as:'result'.
    i := asm alloca:LLVMType intptr as:'i'.
    asm store:(function parameterAt:1) at:i.
    asm store:(LLVMConstant sintptr: 1) at:result.
    asm br:loop.
     
    "/ Generate loop that computes the factorial
    "/ 
    "/ 08    while ( i > 1 ) {
    "/ 09      result = result * i;
    "/ 10      i = i - 1.
    "/ 11    }
    "/ 
    "/ Note, that unlike 'traditional' assemblers, there's no
    "/ fall-through instruction, so we have to introduce a block 
    "/ loop's body which will become a target for conditional's
    "/ then-branch.
    
    asm block:loop.
    asm 
        if:(asm 
                icmp:(asm load:i)
                _:(LLVMConstant sintptr:1)
                cond:LLVMIntSGT)
        then:loopBody
        else:exit.
    asm block:loopBody.
    asm store:(asm mul:(asm load:result) _:(asm load:i)) at:result.
    asm store:(asm sub:(asm load:i) _:(LLVMConstant sintptr:1)) at:i.
    asm br:loop.
     
    "/ Generate return from function
    "/ 
    "/ 12    return result;
    "/ 13 }
    "/ 
    
    asm block:exit.
    asm ret:(asm load:result).
    jit := LLVMExecutionEngine newForModule:module.
    externalFunction := jit externalOfFunction:function.
    self assert:(externalFunction callWith:5) == 120.
    self assert:(externalFunction callWith:1) == 1.

    "
        LLVMExamples run: example5_factorial_with_debug_info
    "

    "Created: / 10-08-2015 / 09:46:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 11-08-2016 / 09:06:54 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example5_factorial_phi
    "A simple factorial using recursive algorithm.
     No overflow or negative value checks. 
     Demonstrates usage of phi node"
    
    | module functionType function asm  
    "Values"       paramIsOneVal paramIsNotOneVal
    "Blocks" entry paramIsOne    paramIsNotOne exit jit externalFunction |

    module := LLVMModule newWithName:testSelector.
    functionType := LLVMType function:{ LLVMType intptr } returning:LLVMType intptr.
    function := module addFunctionNamed:'factorial' type:functionType.
    asm := LLVMIRBuilder new.
    entry := function entry.
    paramIsOne := function addBasicBlockNamed:'paramIsOne'.
    paramIsNotOne := function addBasicBlockNamed:'paramIsNotOne'.
    exit := function addBasicBlockNamed:'exit'.
     
    "/ Generate function setup
    "/ 
    "/ 03   function f(v) {
    "/ 04    return (v == 1
    "/ 05             ?  1
    "/ 07             :  v * f(v - 1)
    "/ 08    )
    
    asm block:entry.
    asm if: (asm icmp:(function parameterAt: 1) _:(LLVMConstant sintptr:1) cond:LLVMIntEQ)
      then: paramIsOne
      else: paramIsNotOne.

    asm block: paramIsOne.
    paramIsOneVal := LLVMConstant sintptr: 1.
    asm br: exit.
    asm block: paramIsNotOne.
    paramIsNotOneVal := asm mul: (asm call: function _: { asm sub: (function parameterAt: 1) _: (LLVMConstant sintptr: 1) })
                              _: (function parameterAt: 1).           
    asm br: exit.
    asm block: exit.
    asm ret: (asm phi: { paramIsOne -> paramIsOneVal . paramIsNotOneVal }).


    jit := LLVMExecutionEngine newForModule:module.
    externalFunction := jit externalOfFunction:function.
    self assert:(externalFunction callWith:5) == 120.
    self assert:(externalFunction callWith:1) == 1.

    "
        LLVMExamples run: example5_factorial_with_debug_info
    "

    "Created: / 21-04-2016 / 22:14:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 22-04-2016 / 09:10:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example6_factorial_with_overflow
    "
     Simple factorial using iterative algorithm.
     This one checks for overflow, if overflow happens,
     return -1"
    
    | module  functionType  function  asm  "Variables"
    result  i  "Blocks"
    entry  loop  loopBody1  loopBody2  exit  overflow  smulWithOverflow  smulWithOverflowValue  jit  externalFunction |

    module := LLVMModule newWithName:testSelector.
    functionType := LLVMType function:{
                    LLVMType intptr
                }
            returning:LLVMType intptr.
    function := module addFunctionNamed:'factorial' type:functionType.
    asm := LLVMIRBuilder new.
    entry := function entry.
    loop := function addBasicBlockNamed:'loop'.
    loopBody1 := function addBasicBlockNamed:'loopBody1'.
    loopBody2 := function addBasicBlockNamed:'loopBody2'.
    exit := function addBasicBlockNamed:'exit'.
    overflow := function addBasicBlockNamed:'overflow'.
     
    "/ Generate function setup
    "/ 
    "/   function f(v) {
    "/     var result;
    "/     var i;
    "/     result = 0;
    "/     i := v;
    
    asm block:entry.
    result := asm alloca:LLVMType intptr as:'result'.
    i := asm alloca:LLVMType intptr as:'i'.
    asm store:(function parameterAt:1) at:i.
    asm store:(LLVMConstant sintptr: 1) at:result.
    asm br:loop.
     
    "/ Generate loop that computes the factorial
    "/ 
    "/     while ( i > 1 ) {
    "/       result = result * i if overflow goto overflow;
    "/       i = i - 1.
    "/     }
    "/ 
    "/ First, get the llvm.smul.with.overflow intrinsic:
    
    smulWithOverflow := module getIntrinsicNamed:'llvm.smul.with.overflow'
            types:{
                    LLVMType intptr
                }.
     
    "/ Now code the loop
    
    asm block:loop.
    asm 
        if:(asm 
                icmp:(asm load:i)
                _:(LLVMConstant sintptr:1)
                cond:LLVMIntSGT)
        then:loopBody1
        else:exit.
    asm block:loopBody1.
    smulWithOverflowValue := asm call:smulWithOverflow
            _:{
                    (asm load:result).
                    (asm load:i)
                }.
    asm 
        if:(asm extractvalue:smulWithOverflowValue at:1)
        then:overflow
        else:loopBody2.
    asm block:loopBody2.
    asm store:(asm extractvalue:smulWithOverflowValue at:0) at:result.
    asm store:(asm sub:(asm load:i) _:(LLVMConstant sintptr:1)) at:i.
    asm br:loop.
     
    "/ Generate return from function
    "/ 
    "/     return result;
    "/ 
    
    asm block:exit.
    asm ret:(asm load:result).
     
    "/ Generate overflow handler
    "/     overflow:
    "/     return -1;
    "/ 
    
    asm block:overflow.
    asm ret:(LLVMConstant sintptr:-1).
    jit := LLVMExecutionEngine newForModule:module.
    externalFunction := jit externalOfFunction:function.
    self assert:(externalFunction callWith:5) == 120.
    self assert:(externalFunction callWith:1) == 1.
    self assert:(externalFunction callWith:120) == -1.

    "sly    LLVMExamples example3_cond"

    "Created: / 14-08-2015 / 06:46:31 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 10-08-2016 / 23:01:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example7_factorial_with_debug_info
    "A simple factorial using iterative algorithm
     with debug info attached. 
    "     

    | module functionType function asm   
    "Variables" result  i  
    "Blocks" entry loop loopBody exit 
    "Debug Info Metadata" dib fileDI compilationUnitDI functionTypeDI functionDI intptrDI resultDI iDI
    jit externalFunction |

    module := LLVMModule newWithName:testSelector.
    dib := module debugInfoBuilder.

    fileDI := dib createFile: Filename currentDirectory / 'factorial.lang'.
    compilationUnitDI := dib createCompilationUnit: Filename currentDirectory / 'factorial.lang' language: LLVM_DW_LANG_lo_user + 10 producer: self class name.

    functionType := LLVMType function:{ LLVMType intptr } returning:LLVMType intptr.
    intptrDI := dib createTypeScalar: 'intptr' type: LLVMType intptr encoding: LLVM_DW_ATE_signed.
    functionTypeDI := dib createTypeFunction: { intptrDI }.
    function := module addFunctionNamed:'factorial' type:functionType.
    functionDI := dib createFunction: 'factorial' in: compilationUnitDI file: fileDI line: 03 type: functionTypeDI local: false definition: true optimized: false.
    dib createParameterVariable: 'v' in: functionDI file: fileDI line: 03 type: intptrDI flags: 0 index: 1.
    asm := LLVMIRBuilder new.
    entry := function entry.
    loop := function addBasicBlockNamed:'loop'.
    loopBody := function addBasicBlockNamed:'loopBody'.
    exit := function addBasicBlockNamed:'exit'.
     
    "/ Generate function setup
    "/ 
    "/ 03  function f(v) {
    "/ 04    var result;
    "/ 05    var i;
    "/ 06    result = 0;
    "/ 07    i := v;
    
    asm block:entry.
    asm line: 4 column: 3 scope: functionDI.
    result := asm alloca:LLVMType intptr as:'result'.
    resultDI := dib createAutomaticVariable: 'result' in: functionDI file: fileDI line: 4 type: intptrDI.
    dib insertDeclare: result variable: resultDI expression: dib createExpression location: asm location atEndOf: entry.

    asm line: 5 column: 3 scope: functionDI.
    i := asm alloca:LLVMType intptr as:'i'.
    iDI := dib createAutomaticVariable: 'i' in: functionDI file: fileDI line: 4 type: intptrDI.
    dib insertDeclare: i variable: iDI expression: dib createExpression location: asm location atEndOf: entry.

    asm line: 6 column: 3 scope: functionDI.
    asm store:(function parameterAt:1) at:i.

    asm line: 7 column: 3 scope: functionDI.
    asm store:(LLVMConstant sintptr: 1) at:result.
    asm br:loop.
     
    "/ Generate loop that computes the factorial
    "/ 
    "/   08  while ( i > 1 ) {
    "/   09    result = result * i;
    "/   10    i = i - 1.
    "/   11  }
    "/ 
    "/ Note, that unlike 'traditional' assemblers, there's no
    "/ fall-through instruction, so we have to introduce a block 
    "/ loop's body which will become a target for conditional's
    "/ then-branch.
    
    asm block:loop.
    asm line: 8 column: 3 scope: functionDI.
    asm 
        if:(asm 
                icmp:(asm load:i)
                _:(LLVMConstant sintptr:1)
                cond:LLVMIntSGT)
        then:loopBody
        else:exit.
    asm block:loopBody.
    asm line: 9 column: 3 scope: functionDI.
    asm store:(asm mul:(asm load:result) _:(asm load:i)) at:result.
    asm line: 10 column: 3 scope: functionDI.
    asm store:(asm sub:(asm load:i) _:(LLVMConstant sintptr:1)) at:i.
    asm line: 11 column: 3 scope: functionDI.
    asm br:loop.
     
    "/ Generate return from function
    "/ 
    "/ 12    return result;
    "/ 13  }
    "/ 

    asm block:exit.
    asm line: 12 column: 3 scope: functionDI.
    asm ret:(asm load:result).

    dib finish.
    self halt.
    "
    To generate stand-alone executable do the following:

    1) Execute following to write LLVM IR to /tmp/factorial.ll

        module writeBitcodeToFile: '/tmp/factorial.bc'

    2) Compile it into an object file

        llc-3.8 --filetype=obj factorial.bc

    3) Write a simple main.c to call factorial():

        '/tmp/main.c' asFilename writingFileDo:[:f | f nextPutAll: 'int main(int argc, char **argv) { factorial(5); exit(0); }' ].

    4) Compile main.c and link it with factorial.o

        gcc -o main main.c factorial.o

    To actually debug it, first write the pseudo-code for the factorial:

        '/tmp/factorial.lang' asFilename writingFileDo:[ :f|
            f nextPutLine: ''.
            f nextPutLine: ''.
            f nextPutLine: 'function factorial(v) {'.
            f nextPutLine: '  var result;'.
            f nextPutLine: '  var i;'.
            f nextPutLine: '  result = 0;'.
            f nextPutLine: '  i := v;'.
            f nextPutLine: '  while ( i > 1 ) {'.
            f nextPutLine: '    result = result * i;'.
            f nextPutLine: '    i = i - 1.'.
            f nextPutLine: '  }'.
            f nextPutLine: '  return result;'.
            f nextPutLine: '}'.
        ]

    Then debug it using gdb:

            gdb main
    "


    jit := LLVMExecutionEngine newForModule:module.
    externalFunction := jit externalOfFunction:function.
    self assert:(externalFunction callWith:5) == 120.
    self assert:(externalFunction callWith:1) == 1.

    "
     LLVMExamples example7_factorial_with_debug_info"

    "Created: / 14-08-2015 / 06:46:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 06-02-2016 / 15:28:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified (comment): / 21-04-2016 / 21:37:35 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example8_data_at_fixed_address
    "
    Creates a function that returns an int value at fixed address
    (known at compilation time)
    "    

    | module 
     functionType function asm glb val |

    module := LLVMModule newWithName: testSelector.

    functionType := LLVMType function: {  } returning: LLVMType int32.
    function := module addFunctionNamed: 'test' type: functionType.

    asm := function builder.
    glb := asm int: (LLVMConstant uintptr: 1234) toPtr: LLVMType int32 pointer. 
    val := asm load: (asm gep: glb at: #(1)).
    asm ret: val.

    self halt.
    "
    LLVMExamples new example8_data_at_fixed_address
    "

    "Created: / 11-02-2016 / 20:15:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 12-02-2016 / 11:11:28 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!

example9_memset
    "
    Creates a function that clears alloca()ted structure,
    Shows use of llvm.memset intrinsic.
    "    

    | module functionType function asm pointTy point |

    module := LLVMModule newWithName: testSelector ? 'test'.

    pointTy := LLVMType named: 'point_t'.
    pointTy elementTypes: { LLVMType int32 . LLVMType int32 }.

    functionType := LLVMType function: {  } returning: LLVMType void.
    function := module addFunctionNamed: 'test' type: functionType.

    asm := function builder.
    point := asm alloca: pointTy as: 'point'.
    asm memset: point  _: (LLVMConstant uint8: 0) _: (LLVMConstant uint64: (LLVMType int32 sizeInBytes * 2))  _: 1 _: false.
    asm ret.

    module verify.
    self halt.
    "
    LLVMExamples new example9_memset
    "

    "Created: / 06-07-2016 / 00:01:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    "Modified: / 08-07-2016 / 15:44:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!LLVMExamples class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !