PageRenderTime 19ms CodeModel.GetById 5ms app.highlight 3ms RepoModel.GetById 5ms app.codeStats 0ms

/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
  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