Skip to content

Instantly share code, notes, and snippets.

@iK4tsu
Last active February 26, 2024 19:03
Show Gist options
  • Save iK4tsu/5e8a714e3aa35f5b5b7f52d798267493 to your computer and use it in GitHub Desktop.
Save iK4tsu/5e8a714e3aa35f5b5b7f52d798267493 to your computer and use it in GitHub Desktop.
LLVM-C 'Hello World' using D Programming Language
module app;
import llvm;
int main()
{
// module preparation
LLVMModuleRef mod = LLVMModuleCreateWithName("main".ptr);
// build a main function
// functions in LLVM are created by steps
// first define the function type
// second append the body
// third add functionality to the body
LLVMTypeRef funType = LLVMFunctionType(LLVMInt32Type(), null, 0, false); // create the function type
LLVMValueRef mainFn = LLVMAddFunction(mod, "main".ptr, funType); // add function 'main' to 'mainMod'
LLVMSetLinkage(mainFn, LLVMExternalLinkage); // update the linkage of 'main'
LLVMBasicBlockRef mainBody = LLVMAppendBasicBlock(mainFn, "mainBody".ptr); // create a body for 'main'
// every operation must be performed using a builder
LLVMBuilderRef builder = LLVMCreateBuilder(); // create a builder for 'mainBody'
LLVMPositionBuilderAtEnd(builder, mainBody); // add the builder to 'mainBody'
// use libc's printf function to print 'hello world'
// the following steps are similar to what was done above
// the function type has it's return type as a pointer
// this is because it is function pointer being declared
// since 'printf' is a function of libc, no body is added
LLVMTypeRef i8p = LLVMPointerType(LLVMInt8Type(), 8); // create the return type
LLVMTypeRef printfType = LLVMFunctionType(LLVMInt32Type(), &i8p, 1, true); // create the function type
LLVMValueRef printfFun = LLVMAddFunction(mod, "printf".ptr, printfType); // add function 'printf' to 'mainMod'
LLVMSetLinkage(printfFun, LLVMExternalLinkage); // update the linkage of 'printf'
// create the content to pass into 'printf' and call the function
// once again, operations are performed using a builder
// in this case, the builder associated with function 'main'
LLVMValueRef str = LLVMBuildGlobalStringPtr(builder, "hello world\n".ptr, "hello_world");
LLVMValueRef format = LLVMBuildPointerCast(builder, format, LLVMPointerType(LLVMInt8Type(), 8), "format");
LLVMValueRef printfCall = LLVMBuildCall(builder, printfFun, &format, 1, "call");
// setup the return value
// return '0' from 'main'
LLVMBuildRet(builder, LLVMConstInt(LLVMInt32Type(), 0, true));
// check the module for any potential errors
char* err;
LLVMVerifyModule(mod, LLVMAbortProcessAction, &err);
LLVMDisposeMessage(err);
// prepare the execution engine to run the program
LLVMExecutionEngineRef engine;
err = null;
LLVMInitializeNativeTarget();
if (LLVMCreateExecutionEngineForModule(&engine, mod, &err) != LLVMErrorSuccess)
{
import std.stdio : stderr;
import std.string : fromStringz;
stderr.writefln!"[Error]: [Execution Engine]: %s"(err.fromStringz());
return 1;
}
LLVMInitializeNativeAsmPrinter();
LLVMInitializeNativeAsmParser();
// access function 'main'
alias MainFn = extern (C) int function();
auto fn = cast(MainFn) LLVMGetFunctionAddress(engine, "main".ptr);
// print LLVM-IR
import std.stdio : writeln;
import std.string : fromStringz;
LLVMPrintModuleToString(mod).fromStringz.writeln();
// run function 'main'
return fn();
}
{
"authors": [ "João Lourenço" ],
"copyright": "Copyright © 2022, João Lourenço",
"description": "LLVM-C 'Hello World' using D",
"license": "GPL-3.0",
"name": "llvm-hello-world",
"dependencies": {
"llvm-d": "~>3.0.0"
},
"libs": ["LLVM-14", "LTO"],
"versions": ["LLVM_8_0_0"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment