{"id":14991217,"url":"https://github.com/ftomassetti/kllvm","last_synced_at":"2025-06-15T09:08:09.374Z","repository":{"id":39184522,"uuid":"92651405","full_name":"ftomassetti/kllvm","owner":"ftomassetti","description":"Kotlin library to work with LLVM","archived":false,"fork":false,"pushed_at":"2022-06-24T08:59:10.000Z","size":101,"stargazers_count":59,"open_issues_count":2,"forks_count":9,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-04-12T03:36:56.649Z","etag":null,"topics":["kotlin","llvm","llvm-bindings","llvm-ir"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ftomassetti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-05-28T09:20:25.000Z","updated_at":"2024-12-17T19:22:06.000Z","dependencies_parsed_at":"2022-08-24T04:50:09.857Z","dependency_job_id":null,"html_url":"https://github.com/ftomassetti/kllvm","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/ftomassetti/kllvm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ftomassetti%2Fkllvm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ftomassetti%2Fkllvm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ftomassetti%2Fkllvm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ftomassetti%2Fkllvm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ftomassetti","download_url":"https://codeload.github.com/ftomassetti/kllvm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ftomassetti%2Fkllvm/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259949682,"owners_count":22936411,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kotlin","llvm","llvm-bindings","llvm-ir"],"created_at":"2024-09-24T14:21:47.062Z","updated_at":"2025-06-15T09:08:09.353Z","avatar_url":"https://github.com/ftomassetti.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# KLLVM\n\nKLLVM stands for Kotlin-LLVM. It is intended as a library to work with LLVM in Kotlin.\n\nCurrently it supports the generation of IR code. The rationale is that there are currently no decent options to use LLVM\nfrom the JVM: while there is an autogenerated wrapper of the \n[LLVM C++ API for Java](https://github.com/bytedeco/javacpp-presets/tree/master/llvm) \nit is unusable. For this reason the best option seems to generate the textual representation of IR code to later compile\nit to object file (or interpret it directly) using LLVM utilities.\n\n## How to use it\n\nIn the following example we show how to generate a simple application take takes two parameters, sum them and print the\nresult.\n\n```kotlin\n    @test fun generateSum() {\n        val EXIT_CODE_OK = 0\n        val EXIT_CODE_WRONG_PARAMS = 1\n        val N_PARAMS_EXPECTED = 2\n        val STRING_TYPE = Pointer(I8Type)\n\n        val module = ModuleBuilder()\n        val mainFunction = module.createMainFunction()\n\n        val atoiDeclaration = FunctionDeclaration(\"atoi\", I32Type, listOf(), varargs = true)\n        module.addDeclaration(atoiDeclaration)\n        module.addDeclaration(FunctionDeclaration(\"printf\", I32Type, listOf(STRING_TYPE), varargs = true))\n\n        val okParamsBlock = mainFunction.createBlock(\"okParams\")\n        val koParamsBlock = mainFunction.createBlock(\"koParams\")\n\n        val comparisonResult = mainFunction.tempValue(Comparison(ComparisonType.Equal,\n                mainFunction.paramReference(0), IntConst(N_PARAMS_EXPECTED + 1, I32Type)))\n        mainFunction.addInstruction(IfInstruction(comparisonResult.reference(), okParamsBlock, koParamsBlock))\n\n        // OK Block : convert to int, sum, and print\n        val aAsStringPtr = okParamsBlock.tempValue(GetElementPtr(STRING_TYPE, mainFunction.paramReference(1), IntConst(1, I64Type)))\n        val aAsString = okParamsBlock.load(aAsStringPtr.reference())\n        val aAsInt = okParamsBlock.tempValue(CallWithBitCast(atoiDeclaration, aAsString))\n        val bAsStringPtr = okParamsBlock.tempValue(GetElementPtr(STRING_TYPE, mainFunction.paramReference(1), IntConst(2, I64Type)))\n        val bAsString = okParamsBlock.load(bAsStringPtr.reference())\n        val bAsInt = okParamsBlock.tempValue(CallWithBitCast(atoiDeclaration, bAsString))\n        val sum = okParamsBlock.tempValue(IntAddition(aAsInt.reference(), bAsInt.reference()))\n        okParamsBlock.addInstruction(Printf(mainFunction.stringConstForContent(\"Result: %d\\n\").reference(), sum.reference()))\n        okParamsBlock.addInstruction(ReturnInt(EXIT_CODE_OK))\n\n        // KO Block : error message and exit\n        koParamsBlock.addInstruction(Printf(mainFunction.stringConstForContent(\"Please specify two arguments\").reference()))\n        koParamsBlock.addInstruction(ReturnInt(EXIT_CODE_WRONG_PARAMS))\n\n        println(module.IRCode())\n        assertEquals(\"\"\"@stringConst0 = private unnamed_addr constant [12 x i8] c\"Result: %d\\0A\\00\"\n@stringConst1 = private unnamed_addr constant [29 x i8] c\"Please specify two arguments\\00\"\n\n\n\ndeclare i32 @atoi(...)\ndeclare i32 @printf(i8*, ...)\n\ndefine i32 @main(i32, i8**) {\n    \n    ; unnamed block\n    %tmpValue0 = icmp eq i32 %0, 3\n    br i1 %tmpValue0, label %okParams, label %koParams\n\n    okParams:\n    %tmpValue1 = getelementptr inbounds i8*, i8** %1, i64 1\n    %tmpValue2 = load i8*, i8** %tmpValue1\n    %tmpValue3 = call i32 (i8*, ...) bitcast (i32 (...)* @atoi to i32 (i8*, ...)*)(i8* %tmpValue2)\n    %tmpValue4 = getelementptr inbounds i8*, i8** %1, i64 2\n    %tmpValue5 = load i8*, i8** %tmpValue4\n    %tmpValue6 = call i32 (i8*, ...) bitcast (i32 (...)* @atoi to i32 (i8*, ...)*)(i8* %tmpValue5)\n    %tmpValue7 = add i32 %tmpValue3, %tmpValue6\n    call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([12 x i8], [12 x i8]* @stringConst0, i32 0, i32 0), i32 %tmpValue7)\n    ret i32 0\n\n    koParams:\n    call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @stringConst1, i32 0, i32 0))\n    ret i32 1\n\n}\"\"\", module.IRCode().trim())\n    }\n```\n\nBy using KLLVM is it possible to programmatically build the program and the obtain the IR code.\nThis IR code can then be interpreted using the _lli_ command from LLVM.\n\nIt can also be compiled into an executable by running:\n\n```\nllc -filetype=obj example.ll\nclang example.o -o example\n```\n\n## Status\n\nThe library is currently used to compile to IR two Domain Specific Languages. The code is presented in the book \n[How to create pragmatic, lightweight languages](https://tomassetti.me/create-languages).\n\n## Future\n\nWe plan to add new features following the requests of the community. One possible option could be to create a wrapper\naround the javacpp-presets for LLVM.   \n\n## License\n\nThis project is released under the Apache License V2.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fftomassetti%2Fkllvm","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fftomassetti%2Fkllvm","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fftomassetti%2Fkllvm/lists"}