/src/wrappers/llvm/examples/plain/llvm_example.e

http://github.com/tybor/Liberty · Specman e · 155 lines · 110 code · 20 blank · 25 comment · 0 complexity · 8b782684448bcef0a8c0e3c3f403dcfb MD5 · raw file

  1. class LLVM_EXAMPLE
  2. -- A plain example of LLVM that outputs bytecode of a module. Pass it to llvm-dis
  3. -- Currently we must use Makefile becuase even if we used C bindings we
  4. -- must use C++ linker. This could be achieved changing compile modes; it
  5. -- is more easily approached using make. See
  6. -- http://npcontemplation.blogspot.com/2008/06/secret-of-llvm-c-bindings.html
  7. -- TODO: once working, make this example more "Libertish", i.e. removing
  8. -- make_make and turning main into an once feature
  9. insert
  10. SHARED_LLVM
  11. LLVM_C_TYPES
  12. LLVM_VALUES_FACTORY
  13. CORE_EXTERNALS
  14. create {ANY} make
  15. feature {} -- Creation
  16. make
  17. do
  18. create module.with_name("llvm-example")
  19. use_plugin
  20. make_muladd
  21. make_puts
  22. make_main
  23. module.write_bitcode_to(std_output)
  24. std_error.put_string(once "End of example reached.%N")
  25. -- verifyModule(*Mod, PrintMessageAction);
  26. -- create pass_manager
  27. -- pass_manager.add(createPrintModulePass(&outs()));
  28. -- pass_manager.run(module)
  29. end
  30. make_muladd
  31. local x,y,z, tmp,tmp2,ret: LLVM_VALUE; param_iter: ITERATOR[LLVM_VALUE]
  32. do
  33. create muladd_type.make(int_32, <<int_32,int_32,int_32>>,False)
  34. -- `muladd' is a function that takes three 32-bit integers, returns a 32bit integer and is not variadic.
  35. muladd := module.new_function("mul_add",muladd_type)
  36. calling_convention.set_ccall_conv
  37. muladd.set_calling_convention(calling_convention)
  38. -- set parameters name
  39. check
  40. muladd.parameters_count=3
  41. end
  42. -- Set parameters' names, keeping a reference to the value for further usage
  43. param_iter := muladd.new_parameter_iterator
  44. param_iter.start; x:=param_iter.item; x.set_name("x")
  45. param_iter.next; y:=param_iter.item; y.set_name("y")
  46. param_iter.next; z:=param_iter.item; z.set_name("z")
  47. std_error.put_string("[
  48. muladd.do_all_parameters (agent {LLVM_VALUE}.print_on(std_error))
  49. violates the not_locked precondition in ANY.print_on
  50. ]")
  51. check
  52. muladd.parameter(0).name.is_equal("x")
  53. muladd.parameter(1).name.is_equal("y")
  54. muladd.parameter(2).name.is_equal("z")
  55. muladd.for_all_parameters(agent name_not_void)
  56. muladd.exists_parameter(agent name_is(?,"y"))
  57. end
  58. -- Add function body
  59. create block.appended_in_context(global_context,muladd,"entry-block")
  60. create builder
  61. builder.position_at_end_of(block)
  62. tmp := builder.mul(x,y,"tmp")
  63. tmp2 := builder.add(tmp,z,"tmp2")
  64. ret := builder.return(tmp2)
  65. end
  66. make_puts
  67. -- The external function "int puts(const char *s);"
  68. do
  69. create puts_type.make(int_32,<<string>>,False)
  70. puts := module.new_function("puts",puts_type )
  71. puts.set_external_linkage
  72. ensure puts/=Void
  73. end
  74. make_struct
  75. do
  76. -- struct will contain an int, a bool and a 8bit integer.
  77. create struct_type.make(<<int_32,bool,int_8>>,False)
  78. end
  79. make_main
  80. -- Emit the usual entry point function of a C program: "int main (int argc, char *argv[]);"
  81. local msg,puts_arg, tmp: LLVM_VALUE; argv_type: LLVM_POINTER_TYPE;
  82. do
  83. -- main will be the usual entry point of a C program: "int main (int argc, char *argv[]);"
  84. create argv_type.make(string_type) -- argv is a "pointer to/an array of" arguments
  85. create main_type.make(int_32,<<int_32, argv_type>>, False)
  86. main := module.new_function("main",main_type)
  87. calling_convention.set_ccall_conv
  88. main.set_calling_convention(calling_convention)
  89. create block.appended_in_context(global_context,main,"main-first-block")
  90. create builder.at_end_of(block)
  91. msg := module.local_string("Hello Liberty!")
  92. puts_arg := builder.bit_cast(msg,pointer(int_8),"cast from (n x i8)* to i8*")
  93. std_error.put_string(once "Invoking puts%N")
  94. tmp := builder.call(puts,<<puts_arg>>,"invoking-puts")
  95. std_error.put_string(once "Puts invoked%N")
  96. -- Always return 1
  97. tmp := builder.return (create {LLVM_CONSTANT_INT}.integer_32(1))
  98. end
  99. use_plugin
  100. -- dummy feature to trigger plugin usage
  101. local p: POINTER
  102. do
  103. p:=llvmint32type
  104. end
  105. feature {} -- tests agents
  106. name_not_void (a_value: LLVM_VALUE): BOOLEAN
  107. require a_value/=Void
  108. do
  109. Result := a_value.name/=Void
  110. end
  111. name_is (a_value: LLVM_VALUE; a_name: ABSTRACT_STRING): BOOLEAN
  112. require
  113. a_value/=Void
  114. a_name/=Void
  115. do
  116. Result := a_value.name.is_equal(a_name)
  117. end
  118. feature {ANY} -- data
  119. calling_convention: LLVMCALL_CONV_ENUM
  120. module: LLVM_MODULE
  121. builder: LLVM_BUILDER
  122. block: LLVM_BASIC_BLOCK
  123. -- pass_manager: LLVM_PASS_MANAGER
  124. feature {} -- Functions
  125. muladd: LLVM_FUNCTION
  126. -- A function computes Result=x*y+z.
  127. main: LLVM_FUNCTION
  128. -- The famous main function of C language
  129. puts: LLVM_FUNCTION
  130. feature {} -- Types
  131. main_type, puts_type: LLVM_FUNCTION_TYPE
  132. struct_type: LLVM_STRUCT_TYPE
  133. muladd_type: LLVM_FUNCTION_TYPE
  134. end -- class LLVM_EXAMPLE
  135. -- Copyright (C) 2009-2017: Paolo Redaelli