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