@designliquido/llvm-bindings 2.0.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.github/workflows/build.yml +2 -2
  2. package/CHANGELOG.md +1 -0
  3. package/CMakeLists.txt +2 -2
  4. package/README.md +1 -0
  5. package/cmake/LLVM.cmake +1 -1
  6. package/package.json +4 -6
  7. package/src/IR/Intrinsic.cpp +0 -1
  8. package/tests/IR/OpaquePointer.spec.ts +39 -0
  9. package/tests/IR/Type.spec.ts +24 -0
  10. package/tests/fixtures/add.spec.ts +24 -0
  11. package/tests/fixtures/attribute.spec.ts +27 -0
  12. package/tests/fixtures/bitcodeWriter.spec.ts +42 -0
  13. package/tests/fixtures/class.spec.ts +30 -0
  14. package/tests/fixtures/debugInfo.spec.ts +73 -0
  15. package/tests/fixtures/exception.spec.ts +42 -0
  16. package/tests/fixtures/fibonacci.spec.ts +36 -0
  17. package/tests/fixtures/gep.spec.ts +27 -0
  18. package/tests/fixtures/intrinsic.spec.ts +29 -0
  19. package/tests/fixtures/linker.spec.ts +30 -0
  20. package/tests/fixtures/str.spec.ts +14 -0
  21. package/tests/fixtures/switch.spec.ts +45 -0
  22. package/tests/fixtures/unary.spec.ts +44 -0
  23. package/tests/fixtures/variable.spec.ts +25 -0
  24. package/test/add.ts +0 -32
  25. package/test/attribute.ts +0 -37
  26. package/test/bitcodeWriter.ts +0 -44
  27. package/test/class.ts +0 -39
  28. package/test/debugInfo.ts +0 -181
  29. package/test/exception.ts +0 -57
  30. package/test/fibonacci.ts +0 -44
  31. package/test/gep.ts +0 -42
  32. package/test/index.ts +0 -33
  33. package/test/intrinsic.ts +0 -35
  34. package/test/linker.ts +0 -48
  35. package/test/str.ts +0 -19
  36. package/test/switch.ts +0 -58
  37. package/test/target.ts +0 -14
  38. package/test/type.ts +0 -21
  39. package/test/unary.ts +0 -53
  40. package/test/variable.ts +0 -37
  41. /package/{test → tests/fixtures}/bitcode/add.bc +0 -0
@@ -15,8 +15,8 @@ on:
15
15
  - 'LICENSE'
16
16
 
17
17
  env:
18
- LLVM_VERSION: 16.0.6
19
- LLVM_VERSION_MAJOR: 16
18
+ LLVM_VERSION: 17.0.6
19
+ LLVM_VERSION_MAJOR: 17
20
20
 
21
21
  jobs:
22
22
  build-push:
package/CHANGELOG.md CHANGED
@@ -1,3 +1,4 @@
1
+ # [2.0.0](https://github.com/DesignLiquido/llvm-bindings/compare/v1.0.0...v2.0.0) (2026-03-08)
1
2
  # [1.0.0](https://github.com/DesignLiquido/llvm-bindings/compare/v0.4.2...v1.0.0) (2026-03-08)
2
3
 
3
4
 
package/CMakeLists.txt CHANGED
@@ -19,8 +19,8 @@ add_library(${PROJECT_NAME} SHARED ${CMAKE_JS_SRC} ${SOURCE_FILES})
19
19
  set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node" LINKER_LANGUAGE CXX)
20
20
 
21
21
  if (MSVC)
22
- # cmake-js forces /MT (MultiThreaded static CRT), but LLVM 15 prebuilt Windows
23
- # libraries were compiled with /MD (MultiThreadedDLL dynamic CRT). Override
22
+ # cmake-js forces /MT (MultiThreaded static CRT), but LLVM prebuilt Windows
23
+ # libraries are compiled with /MD (MultiThreadedDLL dynamic CRT). Override
24
24
  # per-target so the linker can resolve __imp_strdup, __imp_read, etc. from ucrtbase.dll.
25
25
  set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
26
26
  endif ()
package/README.md CHANGED
@@ -150,6 +150,7 @@ To opt into opaque pointers, pass an `LLVMContext` to `PointerType.get` / `getUn
150
150
  | (original llvm-bindings repo) 0.4.x | 14.0.x |
151
151
  | (@designliquido/llvm-bindings) 0.1.x | 14.0.x |
152
152
  | (@designliquido/llvm-bindings) 1.0.x | 15.0.x |
153
+ | (@designliquido/llvm-bindings) 2.0.x | 16.0.x |
153
154
 
154
155
  ## Acknowledgments
155
156
 
package/cmake/LLVM.cmake CHANGED
@@ -7,7 +7,7 @@ if (CMAKE_HOST_APPLE)
7
7
  endforeach ()
8
8
  endif ()
9
9
 
10
- find_package(LLVM 16 REQUIRED CONFIG)
10
+ find_package(LLVM 17 REQUIRED CONFIG)
11
11
 
12
12
  message(STATUS "Found LLVM ${LLVM_PACKAGE_VERSION}")
13
13
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@designliquido/llvm-bindings",
3
- "version": "2.0.0",
3
+ "version": "4.0.0",
4
4
  "description": "LLVM bindings for Node.js/JavaScript/TypeScript",
5
5
  "keywords": [
6
6
  "llvm",
@@ -25,14 +25,13 @@
25
25
  },
26
26
  "scripts": {
27
27
  "build": "yarn build:ts",
28
- "build:ts": "tsc",
28
+ "build:ts": "yarn tsc",
29
29
  "prepare": "yarn build:ts",
30
30
  "postinstall": "cmake-js compile",
31
31
  "build:debug": "cmake-js build -D",
32
32
  "build:release": "cmake-js build",
33
- "clear": "rimraf build dist",
34
- "test:legacy": "ts-node test/index.ts",
35
- "test": "yarn build:ts && yarn test:legacy && yarn jest --verbose",
33
+ "clear": "yarn rimraf build dist",
34
+ "test": "yarn build:ts && yarn jest --verbose",
36
35
  "release:patch": "release-it patch",
37
36
  "release:minor": "release-it minor",
38
37
  "release:major": "release-it major"
@@ -51,7 +50,6 @@
51
50
  "release-it": "^19.2.4",
52
51
  "rimraf": "^6.1.3",
53
52
  "ts-jest": "^28.0.5",
54
- "ts-node": "^10.8.1",
55
53
  "typescript": "^5.9.3"
56
54
  },
57
55
  "jest": {
@@ -81,7 +81,6 @@ void Intrinsic::Init(Napi::Env env, Napi::Object &exports) {
81
81
  intrinsicNS.Set("ctlz", Napi::Number::New(env, llvm::Intrinsic::ctlz));
82
82
  intrinsicNS.Set("ctpop", Napi::Number::New(env, llvm::Intrinsic::ctpop));
83
83
  intrinsicNS.Set("cttz", Napi::Number::New(env, llvm::Intrinsic::cttz));
84
- intrinsicNS.Set("dbg_addr", Napi::Number::New(env, llvm::Intrinsic::dbg_addr));
85
84
  intrinsicNS.Set("dbg_declare", Napi::Number::New(env, llvm::Intrinsic::dbg_declare));
86
85
  intrinsicNS.Set("dbg_label", Napi::Number::New(env, llvm::Intrinsic::dbg_label));
87
86
  intrinsicNS.Set("dbg_value", Napi::Number::New(env, llvm::Intrinsic::dbg_value));
@@ -0,0 +1,39 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Opaque Pointer (LLVM 17)', () => {
4
+ test('PointerType.getUnqual returns a pointer type', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const ptr = llvm.PointerType.getUnqual(llvm.Type.getInt8Ty(context));
7
+ expect(ptr.isPointerTy()).toBe(true);
8
+ });
9
+
10
+ test('PointerType.get(type, addrSpace) returns a pointer type', () => {
11
+ const context = new llvm.LLVMContext();
12
+ const ptr = llvm.PointerType.get(llvm.Type.getInt8Ty(context), 0);
13
+ expect(ptr.isPointerTy()).toBe(true);
14
+ });
15
+
16
+ test('getUnqual, get(AS0), and getInt8PtrTy all resolve to the same type', () => {
17
+ const context = new llvm.LLVMContext();
18
+ const a = llvm.PointerType.getUnqual(llvm.Type.getInt8Ty(context));
19
+ const b = llvm.PointerType.get(llvm.Type.getInt8Ty(context), 0);
20
+ const c = llvm.Type.getInt8PtrTy(context);
21
+ expect(llvm.Type.isSameType(a, b)).toBe(true);
22
+ expect(llvm.Type.isSameType(a, c)).toBe(true);
23
+ });
24
+
25
+ test('pointers in different address spaces are both pointer types', () => {
26
+ const context = new llvm.LLVMContext();
27
+ const as0 = llvm.PointerType.get(llvm.Type.getInt8Ty(context), 0);
28
+ const as1 = llvm.PointerType.get(llvm.Type.getInt8Ty(context), 1);
29
+ expect(as0.isPointerTy()).toBe(true);
30
+ expect(as1.isPointerTy()).toBe(true);
31
+ // Note: isSameType does not currently compare address spaces for opaque
32
+ // pointers — that is a known limitation of the binding's implementation.
33
+ });
34
+
35
+ // The following require a binary rebuilt against LLVM 17:
36
+ // - PointerType.getUnqual(context) — context overload
37
+ // - PointerType.get(context, addrSpace) — context overload
38
+ // - ptr.isOpaque() — method not yet registered
39
+ });
@@ -0,0 +1,24 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Type', () => {
4
+ test('isSameType correctly compares primitive and pointer types', () => {
5
+ const context = new llvm.LLVMContext();
6
+
7
+ const int32 = llvm.Type.getInt32Ty(context);
8
+ const int32b = llvm.IntegerType.get(context, 32);
9
+ const int8Ptr = llvm.Type.getInt8PtrTy(context);
10
+ const unqualPtr = llvm.PointerType.getUnqual(llvm.Type.getInt8Ty(context));
11
+ const voidTy = llvm.Type.getVoidTy(context);
12
+
13
+ expect(llvm.Type.isSameType(int32, int32b)).toBe(true);
14
+ expect(llvm.Type.isSameType(int32, int8Ptr)).toBe(false);
15
+ expect(llvm.Type.isSameType(int32, unqualPtr)).toBe(false);
16
+ expect(llvm.Type.isSameType(int32, voidTy)).toBe(false);
17
+ expect(llvm.Type.isSameType(int32b, int8Ptr)).toBe(false);
18
+ expect(llvm.Type.isSameType(int32b, unqualPtr)).toBe(false);
19
+ expect(llvm.Type.isSameType(int32b, voidTy)).toBe(false);
20
+ expect(llvm.Type.isSameType(int8Ptr, unqualPtr)).toBe(true);
21
+ expect(llvm.Type.isSameType(int8Ptr, voidTy)).toBe(false);
22
+ expect(llvm.Type.isSameType(unqualPtr, voidTy)).toBe(false);
23
+ });
24
+ });
@@ -0,0 +1,24 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Add', () => {
4
+ test('builds and verifies valid IR for an add function', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('add', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const returnType = builder.getInt32Ty();
10
+ const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
11
+ const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
12
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'add', module);
13
+
14
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
15
+ builder.SetInsertPoint(entryBB);
16
+ const paramA = func.getArg(0);
17
+ const paramB = func.getArg(1);
18
+ const result = builder.CreateAdd(paramA, paramB);
19
+ builder.CreateRet(result);
20
+
21
+ expect(llvm.verifyFunction(func)).toBe(false);
22
+ expect(llvm.verifyModule(module)).toBe(false);
23
+ });
24
+ });
@@ -0,0 +1,27 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Attribute', () => {
4
+ test('builds and verifies valid IR with function and parameter attributes', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('attribute', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const returnType = builder.getInt32Ty();
10
+ const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
11
+ const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
12
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'addWithAttributes', module);
13
+
14
+ const noInlineAttr = llvm.Attribute.get(context, llvm.Attribute.AttrKind.NoInline);
15
+ const inRegAttr = llvm.Attribute.get(context, llvm.Attribute.AttrKind.InReg, builder.getInt32Ty());
16
+ func.addFnAttr(noInlineAttr);
17
+ func.addParamAttr(0, inRegAttr);
18
+
19
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
20
+ builder.SetInsertPoint(entryBB);
21
+ const result = builder.CreateAdd(func.getArg(0), func.getArg(1));
22
+ builder.CreateRet(result);
23
+
24
+ expect(llvm.verifyFunction(func)).toBe(false);
25
+ expect(llvm.verifyModule(module)).toBe(false);
26
+ });
27
+ });
@@ -0,0 +1,42 @@
1
+ import fs from 'fs';
2
+ import os from 'os';
3
+ import path from 'path';
4
+ import llvm from '../..';
5
+
6
+ describe('Test Bitcode Writer (IR fixture)', () => {
7
+ const outputPath = path.join(os.tmpdir(), 'llvm-bindings-writer-test.bc');
8
+
9
+ beforeEach(() => {
10
+ if (fs.existsSync(outputPath)) {
11
+ fs.unlinkSync(outputPath);
12
+ }
13
+ });
14
+
15
+ afterEach(() => {
16
+ if (fs.existsSync(outputPath)) {
17
+ fs.unlinkSync(outputPath);
18
+ }
19
+ });
20
+
21
+ test('builds valid IR, writes bitcode, and verifies the output file exists', () => {
22
+ const context = new llvm.LLVMContext();
23
+ const module = new llvm.Module('bitcodeWriter', context);
24
+ const builder = new llvm.IRBuilder(context);
25
+
26
+ const returnType = builder.getInt32Ty();
27
+ const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
28
+ const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
29
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'writer', module);
30
+
31
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
32
+ builder.SetInsertPoint(entryBB);
33
+ const result = builder.CreateAdd(func.getArg(0), func.getArg(1));
34
+ builder.CreateRet(result);
35
+
36
+ expect(llvm.verifyFunction(func)).toBe(false);
37
+ expect(llvm.verifyModule(module)).toBe(false);
38
+
39
+ llvm.WriteBitcodeToFile(module, outputPath);
40
+ expect(fs.existsSync(outputPath)).toBe(true);
41
+ });
42
+ });
@@ -0,0 +1,30 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Class', () => {
4
+ test('builds and verifies valid IR for a struct constructor', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('class', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const elementTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
10
+ const classStructType = llvm.StructType.create(context, elementTypes, 'Person');
11
+
12
+ const paramTypes = [llvm.PointerType.getUnqual(classStructType)];
13
+ const functionType = llvm.FunctionType.get(builder.getVoidTy(), paramTypes, false);
14
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'class_Person_constructor', module);
15
+
16
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
17
+ builder.SetInsertPoint(entryBB);
18
+
19
+ const thisPtr = func.getArg(0);
20
+ const propertyPtr = builder.CreateGEP(classStructType, thisPtr, [
21
+ builder.getInt32(0),
22
+ builder.getInt32(1)
23
+ ]);
24
+ builder.CreateStore(builder.getInt32(111), propertyPtr);
25
+ builder.CreateRetVoid();
26
+
27
+ expect(llvm.verifyFunction(func)).toBe(false);
28
+ expect(llvm.verifyModule(module)).toBe(false);
29
+ });
30
+ });
@@ -0,0 +1,73 @@
1
+ import path from 'path';
2
+ import llvm from '../..';
3
+
4
+ describe('Test Debug Info', () => {
5
+ test('builds and verifies valid IR with DWARF debug information', () => {
6
+ const context = new llvm.LLVMContext();
7
+ const module = new llvm.Module('debugInfo', context);
8
+ const builder = new llvm.IRBuilder(context);
9
+
10
+ module.addModuleFlag(llvm.Module.ModFlagBehavior.Warning, 'Debug Info Version', llvm.LLVMConstants.DEBUG_METADATA_VERSION);
11
+ module.addModuleFlag(llvm.Module.ModFlagBehavior.Warning, 'Dwarf Version', llvm.dwarf.LLVMConstants.DWARF_VERSION);
12
+
13
+ const diBuilder = new llvm.DIBuilder(module);
14
+ const diFile = diBuilder.createFile('debugInfo.ts', __dirname);
15
+ diBuilder.createCompileUnit(llvm.dwarf.SourceLanguage.DW_LANG_C, diFile, 'llvm-bindings', false, '', 0);
16
+ const diBasicType = diBuilder.createBasicType('int', 32, llvm.dwarf.TypeKind.DW_ATE_float);
17
+
18
+ // add function
19
+ const addFuncType = llvm.FunctionType.get(builder.getInt32Ty(), [builder.getInt32Ty(), builder.getInt32Ty()], false);
20
+ const addFunc = llvm.Function.Create(addFuncType, llvm.Function.LinkageTypes.ExternalLinkage, 'add', module);
21
+ const addDIParamTypes = diBuilder.getOrCreateTypeArray([diBasicType, diBasicType, diBasicType]);
22
+ const addDISubroutineType = diBuilder.createSubroutineType(addDIParamTypes);
23
+ const addSubprogram = diBuilder.createFunction(diFile, 'add', '', diFile, 1, addDISubroutineType, 1, llvm.DINode.DIFlags.FlagPrototyped, llvm.DISubprogram.DISPFlags.SPFlagDefinition);
24
+ addFunc.setSubprogram(addSubprogram);
25
+ builder.SetCurrentDebugLocation(new llvm.DebugLoc());
26
+
27
+ const addEntry = llvm.BasicBlock.Create(context, 'entry', addFunc);
28
+ builder.SetInsertPoint(addEntry);
29
+ const allocaA = builder.CreateAlloca(builder.getInt32Ty(), null, 'a');
30
+ builder.CreateStore(addFunc.getArg(0), allocaA);
31
+ diBuilder.insertDeclare(allocaA, diBuilder.createParameterVariable(addSubprogram, 'a', 1, diFile, 1, diBasicType), diBuilder.createExpression(), llvm.DILocation.get(context, 1, 0, addSubprogram), builder.GetInsertBlock()!);
32
+ const allocaB = builder.CreateAlloca(builder.getInt32Ty(), null, 'b');
33
+ builder.CreateStore(addFunc.getArg(1), allocaB);
34
+ diBuilder.insertDeclare(allocaB, diBuilder.createParameterVariable(addSubprogram, 'b', 2, diFile, 1, diBasicType), diBuilder.createExpression(), llvm.DILocation.get(context, 1, 0, addSubprogram), builder.GetInsertBlock()!);
35
+ builder.SetCurrentDebugLocation(llvm.DILocation.get(context, 2, 14, addSubprogram));
36
+ builder.CreateRet(builder.CreateAdd(builder.CreateLoad(builder.getInt32Ty(), allocaA), builder.CreateLoad(builder.getInt32Ty(), allocaB)));
37
+ diBuilder.finalizeSubprogram(addSubprogram);
38
+
39
+ expect(llvm.verifyFunction(addFunc)).toBe(false);
40
+
41
+ // main function
42
+ const mainFuncType = llvm.FunctionType.get(builder.getInt32Ty(), false);
43
+ const mainFunc = llvm.Function.Create(mainFuncType, llvm.Function.LinkageTypes.ExternalLinkage, 'main', module);
44
+ const mainDISubroutineType = diBuilder.createSubroutineType(diBuilder.getOrCreateTypeArray([diBasicType]));
45
+ const mainSubprogram = diBuilder.createFunction(diFile, 'main', '', diFile, 5, mainDISubroutineType, 5, llvm.DINode.DIFlags.FlagPrototyped, llvm.DISubprogram.DISPFlags.SPFlagDefinition);
46
+ mainFunc.setSubprogram(mainSubprogram);
47
+ builder.SetCurrentDebugLocation(new llvm.DebugLoc());
48
+
49
+ const mainEntry = llvm.BasicBlock.Create(context, 'entry', mainFunc);
50
+ builder.SetInsertPoint(mainEntry);
51
+ const allocaC = builder.CreateAlloca(builder.getInt32Ty(), null, 'c');
52
+ const storeA = builder.CreateAlloca(builder.getInt32Ty(), null, 'a');
53
+ const storeB = builder.CreateAlloca(builder.getInt32Ty(), null, 'b');
54
+ diBuilder.insertDeclare(storeA, diBuilder.createAutoVariable(mainSubprogram, 'a', diFile, 6, diBasicType), diBuilder.createExpression(), llvm.DILocation.get(context, 6, 9, mainSubprogram), builder.GetInsertBlock()!);
55
+ builder.SetCurrentDebugLocation(llvm.DILocation.get(context, 6, 9, mainSubprogram));
56
+ builder.CreateStore(builder.getInt32(1), storeA);
57
+ diBuilder.insertDeclare(storeB, diBuilder.createAutoVariable(mainSubprogram, 'b', diFile, 7, diBasicType), diBuilder.createExpression(), llvm.DILocation.get(context, 7, 9, mainSubprogram), builder.GetInsertBlock()!);
58
+ builder.SetCurrentDebugLocation(llvm.DILocation.get(context, 7, 9, mainSubprogram));
59
+ builder.CreateStore(builder.getInt32(2), storeB);
60
+ diBuilder.insertDeclare(allocaC, diBuilder.createAutoVariable(mainSubprogram, 'c', diFile, 8, diBasicType), diBuilder.createExpression(), llvm.DILocation.get(context, 8, 9, mainSubprogram), builder.GetInsertBlock()!);
61
+ builder.SetCurrentDebugLocation(llvm.DILocation.get(context, 8, 13, mainSubprogram));
62
+ const callRet = builder.CreateCall(addFunc, [builder.CreateLoad(builder.getInt32Ty(), storeA), builder.CreateLoad(builder.getInt32Ty(), storeB)]);
63
+ builder.CreateStore(callRet, allocaC);
64
+ builder.SetCurrentDebugLocation(llvm.DILocation.get(context, 9, 5, mainSubprogram));
65
+ builder.CreateRet(builder.CreateLoad(builder.getInt32Ty(), allocaC));
66
+ diBuilder.finalizeSubprogram(mainSubprogram);
67
+
68
+ diBuilder.finalize();
69
+
70
+ expect(llvm.verifyFunction(mainFunc)).toBe(false);
71
+ expect(llvm.verifyModule(module)).toBe(false);
72
+ });
73
+ });
@@ -0,0 +1,42 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Exception', () => {
4
+ test('builds and verifies valid IR for a C++ exception throw', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('exception', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const i8PtrType = builder.getInt8PtrTy();
10
+ const voidType = builder.getVoidTy();
11
+
12
+ const functionType = llvm.FunctionType.get(voidType, false);
13
+ const mainFunc = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'exception', module);
14
+
15
+ const allocExceptionFuncType = llvm.FunctionType.get(i8PtrType, [builder.getInt64Ty()], false);
16
+ const allocExceptionFunc = module.getOrInsertFunction('__cxa_allocate_exception', allocExceptionFuncType);
17
+ const throwFuncType = llvm.FunctionType.get(voidType, [i8PtrType, i8PtrType, i8PtrType], false);
18
+ const throwFunc = module.getOrInsertFunction('__cxa_throw', throwFuncType);
19
+
20
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', mainFunc);
21
+ builder.SetInsertPoint(entryBB);
22
+
23
+ const errMsgStr = builder.CreateGlobalString('error message');
24
+ const tmp1 = builder.CreateCall(allocExceptionFunc, [builder.getInt64(8)]);
25
+ const tmp2 = builder.CreateBitCast(tmp1, llvm.PointerType.getUnqual(builder.getInt8PtrTy()));
26
+ builder.CreateStore(
27
+ builder.CreateInBoundsGEP(
28
+ errMsgStr.getValueType(),
29
+ errMsgStr,
30
+ [builder.getInt64(0), builder.getInt64(0)]
31
+ ),
32
+ tmp2
33
+ );
34
+ const tinfo = new llvm.GlobalVariable(module, builder.getInt8PtrTy(), true, llvm.Function.LinkageTypes.ExternalLinkage, null);
35
+ const tmp3 = builder.CreateBitCast(tinfo, builder.getInt8PtrTy());
36
+ builder.CreateCall(throwFunc, [tmp1, tmp3, llvm.ConstantPointerNull.get(builder.getInt8PtrTy())]);
37
+ builder.CreateUnreachable();
38
+
39
+ expect(llvm.verifyFunction(mainFunc)).toBe(false);
40
+ expect(llvm.verifyModule(module)).toBe(false);
41
+ });
42
+ });
@@ -0,0 +1,36 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Fibonacci', () => {
4
+ test('builds and verifies valid IR for a recursive fibonacci function', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('fibonacci', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const returnType = builder.getInt32Ty();
10
+ const paramTypes = [builder.getInt32Ty()];
11
+ const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
12
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'fibonacci', module);
13
+
14
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
15
+ const thenBB = llvm.BasicBlock.Create(context, 'then', func);
16
+ const elseBB = llvm.BasicBlock.Create(context, 'else', func);
17
+
18
+ builder.SetInsertPoint(entryBB);
19
+ const cond = builder.CreateICmpULE(func.getArg(0), builder.getInt32(1), 'cond');
20
+ builder.CreateCondBr(cond, thenBB, elseBB);
21
+
22
+ builder.SetInsertPoint(thenBB);
23
+ builder.CreateRet(func.getArg(0));
24
+
25
+ builder.SetInsertPoint(elseBB);
26
+ const n_1 = builder.CreateSub(func.getArg(0), builder.getInt32(1), 'n_1');
27
+ const n_2 = builder.CreateSub(func.getArg(0), builder.getInt32(2), 'n_2');
28
+ const ret1 = builder.CreateCall(func, [n_1], 'ret1');
29
+ const ret2 = builder.CreateCall(func, [n_2], 'ret2');
30
+ const result = builder.CreateAdd(ret1, ret2);
31
+ builder.CreateRet(result);
32
+
33
+ expect(llvm.verifyFunction(func)).toBe(false);
34
+ expect(llvm.verifyModule(module)).toBe(false);
35
+ });
36
+ });
@@ -0,0 +1,27 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test GEP', () => {
4
+ test('builds and verifies valid IR using GetElementPtr', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('gep', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const functionType = llvm.FunctionType.get(builder.getVoidTy(), false);
10
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'gep', module);
11
+
12
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
13
+ builder.SetInsertPoint(entryBB);
14
+
15
+ const strAlloca = builder.CreateAlloca(builder.getInt8PtrTy(), null, 'a');
16
+ const printConst = builder.CreateGlobalString('string content', '.str', 0, module);
17
+ const ptr = builder.CreateGEP(printConst.getValueType(), printConst, [
18
+ builder.getInt64(0),
19
+ builder.getInt64(0),
20
+ ]);
21
+ builder.CreateStore(ptr, strAlloca);
22
+ builder.CreateRetVoid();
23
+
24
+ expect(llvm.verifyFunction(func)).toBe(false);
25
+ expect(llvm.verifyModule(module)).toBe(false);
26
+ });
27
+ });
@@ -0,0 +1,29 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Intrinsic', () => {
4
+ test('builds and verifies valid IR using intrinsic declarations', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('intrinsic', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const functionType = llvm.FunctionType.get(builder.getVoidTy(), false);
10
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'intrinsic', module);
11
+
12
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
13
+ builder.SetInsertPoint(entryBB);
14
+
15
+ const debugtrapFn = llvm.Intrinsic.getDeclaration(module, llvm.Intrinsic.debugtrap);
16
+ builder.CreateCall(debugtrapFn, []);
17
+
18
+ llvm.Intrinsic.getDeclaration(module, llvm.Intrinsic.memmove, [
19
+ builder.getInt8PtrTy(),
20
+ builder.getInt8PtrTy(),
21
+ builder.getInt32Ty()
22
+ ]);
23
+
24
+ builder.CreateRetVoid();
25
+
26
+ expect(llvm.verifyFunction(func)).toBe(false);
27
+ expect(llvm.verifyModule(module)).toBe(false);
28
+ });
29
+ });
@@ -0,0 +1,30 @@
1
+ import path from 'path';
2
+ import llvm from '../..';
3
+
4
+ describe('Test Linker', () => {
5
+ test('parses a bitcode file, links it, and verifies the resulting module', () => {
6
+ const context = new llvm.LLVMContext();
7
+ const module = new llvm.Module('linker', context);
8
+ const builder = new llvm.IRBuilder(context);
9
+
10
+ const bitcodePath = path.join(__dirname, 'bitcode/add.bc');
11
+ const err = new llvm.SMDiagnostic();
12
+ const srcModule = llvm.parseIRFile(bitcodePath, err, context);
13
+ expect(llvm.verifyModule(srcModule)).toBe(false);
14
+ expect(llvm.Linker.linkModules(module, srcModule)).toBe(false);
15
+
16
+ const returnType = builder.getInt32Ty();
17
+ const functionType = llvm.FunctionType.get(returnType, false);
18
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'linker', module);
19
+
20
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
21
+ builder.SetInsertPoint(entryBB);
22
+ const addFunc = module.getFunction('add');
23
+ expect(addFunc).toBeInstanceOf(llvm.Function);
24
+ const retVal = builder.CreateCall(addFunc!, [builder.getInt32(1), builder.getInt32(2)]);
25
+ builder.CreateRet(retVal);
26
+
27
+ expect(llvm.verifyFunction(func)).toBe(false);
28
+ expect(llvm.verifyModule(module)).toBe(false);
29
+ });
30
+ });
@@ -0,0 +1,14 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test String', () => {
4
+ test('builds and verifies a module with global strings', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('str', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ builder.CreateGlobalString('HelloWorld', 'str', 0, module);
10
+ builder.CreateGlobalStringPtr('Bye Bye', 'str', 0, module);
11
+
12
+ expect(llvm.verifyModule(module)).toBe(false);
13
+ });
14
+ });
@@ -0,0 +1,45 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Switch', () => {
4
+ test('builds and verifies valid IR for a switch statement', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('switch', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const returnType = builder.getInt32Ty();
10
+ const paramTypes = [builder.getInt32Ty()];
11
+ const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
12
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'switch', module);
13
+
14
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
15
+ const case1BB = llvm.BasicBlock.Create(context, 'switch.case1', func);
16
+ const case2BB = llvm.BasicBlock.Create(context, 'switch.case2', func);
17
+ const defaultCaseBB = llvm.BasicBlock.Create(context, 'switch.default', func);
18
+ const exitBB = llvm.BasicBlock.Create(context, 'switch.exit', func);
19
+
20
+ builder.SetInsertPoint(entryBB);
21
+ const retPtr = builder.CreateAlloca(builder.getInt32Ty(), null, 'ret');
22
+ const switchInst = builder.CreateSwitch(func.getArg(0), defaultCaseBB, 2);
23
+ switchInst.addCase(builder.getInt32(1), case1BB);
24
+ switchInst.addCase(builder.getInt32(2), case2BB);
25
+
26
+ builder.SetInsertPoint(case1BB);
27
+ builder.CreateStore(builder.getInt32(1), retPtr);
28
+ builder.CreateBr(exitBB);
29
+
30
+ builder.SetInsertPoint(case2BB);
31
+ builder.CreateStore(builder.getInt32(2), retPtr);
32
+ builder.CreateBr(exitBB);
33
+
34
+ builder.SetInsertPoint(defaultCaseBB);
35
+ builder.CreateStore(builder.getInt32(3), retPtr);
36
+ builder.CreateBr(exitBB);
37
+
38
+ builder.SetInsertPoint(exitBB);
39
+ const retVal = builder.CreateLoad(builder.getInt32Ty(), retPtr);
40
+ builder.CreateRet(retVal);
41
+
42
+ expect(llvm.verifyFunction(func)).toBe(false);
43
+ expect(llvm.verifyModule(module)).toBe(false);
44
+ });
45
+ });
@@ -0,0 +1,44 @@
1
+ import llvm from '../..';
2
+
3
+ describe('Test Unary', () => {
4
+ test('builds and verifies valid IR for unary not/neg/fneg', () => {
5
+ const context = new llvm.LLVMContext();
6
+ const module = new llvm.Module('unary', context);
7
+ const builder = new llvm.IRBuilder(context);
8
+
9
+ const functionType = llvm.FunctionType.get(builder.getVoidTy(), false);
10
+ const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'unary', module);
11
+
12
+ const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
13
+ builder.SetInsertPoint(entryBB);
14
+
15
+ const boolAlloca = builder.CreateAlloca(builder.getInt1Ty(), null, 'bool_alloca');
16
+ builder.CreateStore(builder.getFalse(), boolAlloca);
17
+ const boolValue = builder.CreateLoad(builder.getInt1Ty(), boolAlloca, 'bool_value');
18
+ const notBoolValue = builder.CreateNot(boolValue, 'not_bool_value');
19
+ builder.CreateStore(notBoolValue, boolAlloca);
20
+
21
+ const flagAlloca = builder.CreateAlloca(builder.getInt64Ty(), null, 'flag_alloca');
22
+ builder.CreateStore(builder.getInt64(123), flagAlloca);
23
+ const flagValue = builder.CreateLoad(builder.getInt64Ty(), flagAlloca, 'flag_value');
24
+ const notFlagValue = builder.CreateNot(flagValue, 'not_flag_value');
25
+ builder.CreateStore(notFlagValue, flagAlloca);
26
+
27
+ const integerAlloca = builder.CreateAlloca(builder.getInt64Ty(), null, 'integer_alloca');
28
+ builder.CreateStore(builder.getInt64(233), integerAlloca);
29
+ const integerValue = builder.CreateLoad(builder.getInt64Ty(), integerAlloca, 'integer_value');
30
+ const negIntegerValue = builder.CreateNeg(integerValue, 'neg_integer_value');
31
+ builder.CreateStore(negIntegerValue, integerAlloca);
32
+
33
+ const floatAlloca = builder.CreateAlloca(builder.getDoubleTy(), null, 'float_alloca');
34
+ builder.CreateStore(llvm.ConstantFP.get(builder.getDoubleTy(), 11.1), floatAlloca);
35
+ const floatValue = builder.CreateLoad(builder.getDoubleTy(), floatAlloca, 'float_value');
36
+ const negFloatValue = builder.CreateFNeg(floatValue, 'neg_float_value');
37
+ builder.CreateStore(negFloatValue, floatAlloca);
38
+
39
+ builder.CreateRetVoid();
40
+
41
+ expect(llvm.verifyFunction(func)).toBe(false);
42
+ expect(llvm.verifyModule(module)).toBe(false);
43
+ });
44
+ });