Guest User

Untitled

a guest
Feb 21st, 2018
101
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.11 KB | None | 0 0
  1. # This program takes a string as a command line argument and produces an executable
  2. # that prints that string. It uses llvmlite to create an object file and gcc to perform
  3. # the linking.
  4.  
  5. import llvmlite.binding as llvm
  6. import llvmlite.ir as ll
  7. import sys
  8. import subprocess
  9.  
  10. # int main()
  11. main_type = ll.FunctionType(ll.IntType(32), [])
  12.  
  13. # int puts(char*);
  14. puts_type = ll.FunctionType(ll.IntType(32), [ll.PointerType(ll.IntType(8))])
  15.  
  16. module = ll.Module()
  17.  
  18. # This will be a declaration because we never add a body. We'll need to link against
  19. # libc to get access to the puts function (gcc will do this automatically)
  20. puts = ll.Function(module, puts_type, name='puts')
  21.  
  22. main = ll.Function(module, main_type, name='main')
  23. bb_entry = main.append_basic_block()
  24.  
  25. builder = ll.IRBuilder()
  26. builder.position_at_end(bb_entry)
  27.  
  28. string = sys.argv[1]
  29. char_array_type = ll.ArrayType(ll.IntType(8), len(string) + 1)
  30. str_constant = ll.GlobalVariable(module, char_array_type, name = "str")
  31. str_constant.global_constant = True
  32. # Initialize the global char array with a 0-terminated bytearray created from the command line argument
  33. str_constant.initializer = ll.Constant(char_array_type, bytearray(string + "\0", encoding = "utf-8"))
  34.  
  35. zero = ll.Constant(ll.IntType(32), 0)
  36. # Get a pointer to the first element of the char array because puts wants a pointer, not an array.
  37. # In C this happens automatically (array decay), but in LLVM we need to do this manually with GEP (get element pointer).
  38. char_pointer = builder.gep(str_constant, [zero, zero])
  39.  
  40. builder.call(puts, [char_pointer])
  41.  
  42. builder.ret(zero)
  43.  
  44. llvm.initialize()
  45. llvm.initialize_native_asmprinter()
  46. llvm.initialize_native_target()
  47. target = llvm.Target.from_default_triple()
  48. target_machine = target.create_target_machine()
  49.  
  50. with open("output.o", "wb") as o:
  51. # The only way I could find to turn an llvmlite.ir.Module into a llvmlite.bindings.ModuleRef
  52. # is by creating an LLVM-assembly string and parsing it. There might be a better way, but I don't know.
  53. o.write(target_machine.emit_object(llvm.parse_assembly(str(module))))
  54.  
  55. # Invoke gcc to do the linking
  56. subprocess.call(["gcc", "output.o", "-o", "output"])
Add Comment
Please, Sign In to add comment