Advertisement
Guest User

Untitled

a guest
Aug 17th, 2019
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.77 KB | None | 0 0
  1. use cranelift::codegen::ir::types;
  2. use cranelift::prelude::*;
  3. use cranelift_faerie::{FaerieBackend, FaerieBuilder, FaerieTrapCollection};
  4. use cranelift_module::{Linkage, Module};
  5.  
  6. fn main() {
  7. // The Faerie backend only supports ISAs with PIC so we add a flag to say it's enabled.
  8. let mut flag_builder = settings::builder();
  9. flag_builder.enable("is_pic").unwrap();
  10.  
  11. // We use the native platform this program is running on.
  12. let isa_builder = cranelift_native::builder().unwrap();
  13. // We create the ISA we will target.
  14. let isa = isa_builder.finish(settings::Flags::new(flag_builder));
  15.  
  16. // Set up a builder using our target ISA.
  17. let builder = FaerieBuilder::new(
  18. isa,
  19. String::from("sum"),
  20. FaerieTrapCollection::Disabled,
  21. cranelift_module::default_libcall_names(),
  22. )
  23. .unwrap();
  24.  
  25. // Set up a module using the FaerieBackend which outputs object files for the selected ISA.
  26. let mut module: Module<FaerieBackend> = Module::new(builder);
  27.  
  28. // The context holds the state of the current code generation.
  29. let mut context = module.make_context();
  30.  
  31. // Creating a function signature of `fn(i32, i32) -> i32`.
  32. context
  33. .func
  34. .signature
  35. .params
  36. .push(AbiParam::new(types::I32));
  37. context
  38. .func
  39. .signature
  40. .params
  41. .push(AbiParam::new(types::I32));
  42. context
  43. .func
  44. .signature
  45. .returns
  46. .push(AbiParam::new(types::I32));
  47.  
  48. // Debug name for the function, not required, usually ExternalName::User is used instead.
  49. context.func.name = cranelift::codegen::ir::ExternalName::TestCase {
  50. length: 3,
  51. ascii: [
  52. b's', b'u', b'm', b'\0', b'\0', b'\0', b'\0', b'\0', b'\0', b'\0', b'\0', b'\0', b'\0',
  53. b'\0', b'\0', b'\0',
  54. ],
  55. };
  56.  
  57. // Function builder context holds the state for function builders.
  58. let mut fnbuilderctx = FunctionBuilderContext::new();
  59. // Create a new function builder to start building a function from the function signature in the context.
  60. let mut fnbuilder = FunctionBuilder::new(&mut context.func, &mut fnbuilderctx);
  61.  
  62. // Create a new ebb block to be the body of the function.
  63. let entry_ebb = fnbuilder.create_ebb();
  64. // Copy the function parameters to the ebb parameters.
  65. fnbuilder.append_ebb_params_for_function_params(entry_ebb);
  66.  
  67. // Point the builder to the ebb block.
  68. fnbuilder.switch_to_block(entry_ebb);
  69. // Seal the current block since there are no other blocks to make.
  70. fnbuilder.seal_block(entry_ebb);
  71.  
  72. // Creating the variables for the function.
  73. let a = Variable::new(0);
  74. let b = Variable::new(1);
  75.  
  76. // Declare the variable types using the function builder.
  77. fnbuilder.declare_var(a, types::I32);
  78. fnbuilder.declare_var(b, types::I32);
  79.  
  80. // Set a to the first ebb param `fn(i32, i32) -> i32`.
  81. // ^
  82. let atmp = fnbuilder.ebb_params(entry_ebb)[0];
  83. fnbuilder.def_var(a, atmp);
  84.  
  85. // Set b to the second ebb param `fn(i32, i32) -> i32`.
  86. // ^
  87. let btmp = fnbuilder.ebb_params(entry_ebb)[1];
  88. fnbuilder.def_var(b, btmp);
  89.  
  90. // Create an add instruction to add a and b.
  91. // a + b
  92. let arg1 = fnbuilder.use_var(a);
  93. let arg2 = fnbuilder.use_var(b);
  94. let addins = fnbuilder.ins().iadd(arg1, arg2);
  95.  
  96. // Create a return instruction to return the result of the add instruction.
  97. fnbuilder.ins().return_(&[addins]);
  98.  
  99. // The function is done so we finallize the function builder.
  100. fnbuilder.finalize();
  101.  
  102. // Declare the function in the module, must be done before they can be used in the module's configured backend.
  103. let functionid = module
  104. .declare_function("sum", Linkage::Export, &context.func.signature)
  105. .unwrap();
  106. // Defined the declared function which finishes the function compilation.
  107. module.define_function(functionid, &mut context).unwrap();
  108.  
  109. // Print the Cranelift IR of the function to stdout.
  110. println!("{}", context.func.display(None));
  111.  
  112. // Clear the context for reuse.
  113. module.clear_context(&mut context);
  114.  
  115. // Finishes all functions in the module which finsihes all the patches and other realloctaions.
  116. module.finalize_definitions();
  117.  
  118. // Consume the module and turn it into the backend's product type, in this case, a binary artifact.
  119. let result = module.finish();
  120.  
  121. // Create a file to write to.
  122. let file = std::fs::File::create("sum.o").unwrap();
  123. // Write the binary artifact to an object file.
  124. result.artifact.write(file).unwrap();
  125.  
  126. // Print disassembly of the compiled function on the terminal.
  127. std::process::Command::new("objdump")
  128. .arg("-d")
  129. .arg("sum.o")
  130. .spawn()
  131. .unwrap()
  132. .wait()
  133. .unwrap();
  134.  
  135. // Example C program using the function we just created.
  136. let csource = "#include <stdio.h>\n\
  137. extern int sum(int, int);\n\
  138. int main() {\n\
  139. printf(\"14 + 48 = %d\\n\", sum(14, 48));\n\
  140. }";
  141.  
  142. // Writes the source to a temporary file.
  143. std::fs::write("tmp.c", csource).unwrap();
  144.  
  145. // Compiles the C code linking it to our object file.
  146. std::process::Command::new("cc")
  147. .arg("tmp.c")
  148. .arg("sum.o")
  149. .arg("-o")
  150. .arg("tmp")
  151. .spawn()
  152. .unwrap()
  153. .wait()
  154. .unwrap();
  155.  
  156. // Executes temporary program.
  157. std::process::Command::new("./tmp")
  158. .spawn()
  159. .unwrap()
  160. .wait()
  161. .unwrap();
  162.  
  163. // Removes the temporary program, the object file, and the temporary C source code.
  164. std::process::Command::new("rm")
  165. .arg("sum.o")
  166. .arg("tmp.c")
  167. .arg("tmp")
  168. .spawn()
  169. .unwrap()
  170. .wait()
  171. .unwrap();
  172. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement