@designliquido/llvm-bindings 1.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.
- package/.github/workflows/build.yml +6 -6
- package/CHANGELOG.md +12 -0
- package/CMakeLists.txt +2 -2
- package/README.md +2 -1
- package/cmake/LLVM.cmake +1 -1
- package/include/IR/DerivedTypes.h +1 -1
- package/include/IR/Type.h +1 -1
- package/include/assert.h +13 -0
- package/llvm-bindings.d.ts +5 -4
- package/package.json +4 -6
- package/src/IR/Attributes.cpp +6 -82
- package/src/IR/DataLayout.cpp +1 -1
- package/src/IR/DerivedTypes.cpp +3 -3
- package/src/IR/Function.cpp +4 -2
- package/src/IR/IRBuilder.cpp +6 -6
- package/src/IR/Intrinsic.cpp +0 -2
- package/src/IR/LLVMContext.cpp +0 -1
- package/src/IR/Type.cpp +4 -4
- package/src/MC/TargetRegistry.cpp +2 -1
- package/src/llvm-bindings.cpp +25 -0
- package/tests/IR/OpaquePointer.spec.ts +39 -0
- package/tests/IR/Type.spec.ts +24 -0
- package/tests/fixtures/add.spec.ts +24 -0
- package/tests/fixtures/attribute.spec.ts +27 -0
- package/tests/fixtures/bitcodeWriter.spec.ts +42 -0
- package/tests/fixtures/class.spec.ts +30 -0
- package/tests/fixtures/debugInfo.spec.ts +73 -0
- package/tests/fixtures/exception.spec.ts +42 -0
- package/tests/fixtures/fibonacci.spec.ts +36 -0
- package/tests/fixtures/gep.spec.ts +27 -0
- package/tests/fixtures/intrinsic.spec.ts +29 -0
- package/tests/fixtures/linker.spec.ts +30 -0
- package/tests/fixtures/str.spec.ts +14 -0
- package/tests/fixtures/switch.spec.ts +45 -0
- package/tests/fixtures/unary.spec.ts +44 -0
- package/tests/fixtures/variable.spec.ts +25 -0
- package/test/add.ts +0 -32
- package/test/attribute.ts +0 -37
- package/test/bitcodeWriter.ts +0 -44
- package/test/class.ts +0 -39
- package/test/debugInfo.ts +0 -181
- package/test/exception.ts +0 -57
- package/test/fibonacci.ts +0 -44
- package/test/gep.ts +0 -42
- package/test/index.ts +0 -33
- package/test/intrinsic.ts +0 -35
- package/test/linker.ts +0 -48
- package/test/str.ts +0 -19
- package/test/switch.ts +0 -58
- package/test/target.ts +0 -14
- package/test/type.ts +0 -21
- package/test/unary.ts +0 -53
- package/test/variable.ts +0 -37
- /package/{test → tests/fixtures}/bitcode/add.bc +0 -0
|
@@ -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
|
+
});
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import llvm from '../..';
|
|
2
|
+
|
|
3
|
+
describe('Test Variable', () => {
|
|
4
|
+
test('builds and verifies valid IR for alloca/store/load', () => {
|
|
5
|
+
const context = new llvm.LLVMContext();
|
|
6
|
+
const module = new llvm.Module('variable', context);
|
|
7
|
+
const builder = new llvm.IRBuilder(context);
|
|
8
|
+
|
|
9
|
+
const returnType = builder.getVoidTy();
|
|
10
|
+
const functionType = llvm.FunctionType.get(returnType, false);
|
|
11
|
+
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'variable', module);
|
|
12
|
+
|
|
13
|
+
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
|
|
14
|
+
builder.SetInsertPoint(entryBB);
|
|
15
|
+
const alloca = builder.CreateAlloca(builder.getInt32Ty(), null, 'a');
|
|
16
|
+
builder.CreateStore(builder.getInt32(11), alloca);
|
|
17
|
+
const value = builder.CreateLoad(builder.getInt32Ty(), alloca);
|
|
18
|
+
const cond = builder.CreateICmpSGT(value, builder.getInt32(10), 'cond');
|
|
19
|
+
builder.CreateSelect(cond, builder.getInt32(10), builder.getInt32(20));
|
|
20
|
+
builder.CreateRetVoid();
|
|
21
|
+
|
|
22
|
+
expect(llvm.verifyFunction(func)).toBe(false);
|
|
23
|
+
expect(llvm.verifyModule(module)).toBe(false);
|
|
24
|
+
});
|
|
25
|
+
});
|
package/test/add.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import llvm from '..';
|
|
3
|
-
|
|
4
|
-
export default function testAdd(): void {
|
|
5
|
-
const filename = path.basename(__filename);
|
|
6
|
-
const context = new llvm.LLVMContext();
|
|
7
|
-
const module = new llvm.Module(filename, context);
|
|
8
|
-
const builder = new llvm.IRBuilder(context);
|
|
9
|
-
|
|
10
|
-
const returnType = builder.getInt32Ty();
|
|
11
|
-
const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
|
|
12
|
-
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
|
|
13
|
-
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'add', module);
|
|
14
|
-
|
|
15
|
-
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
|
|
16
|
-
builder.SetInsertPoint(entryBB);
|
|
17
|
-
const paramA = func.getArg(0);
|
|
18
|
-
const paramB = func.getArg(1);
|
|
19
|
-
const result = builder.CreateAdd(paramA, paramB);
|
|
20
|
-
builder.CreateRet(result);
|
|
21
|
-
|
|
22
|
-
console.log(module.print());
|
|
23
|
-
|
|
24
|
-
if (llvm.verifyFunction(func)) {
|
|
25
|
-
console.error(`${filename}: verifying the 'add' function failed`);
|
|
26
|
-
process.exit(1);
|
|
27
|
-
}
|
|
28
|
-
if (llvm.verifyModule(module)) {
|
|
29
|
-
console.error(`${filename}: verifying the module failed`);
|
|
30
|
-
process.exit(1);
|
|
31
|
-
}
|
|
32
|
-
}
|
package/test/attribute.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import llvm from '..';
|
|
3
|
-
|
|
4
|
-
export default function testAttribute(): void {
|
|
5
|
-
const filename = path.basename(__filename);
|
|
6
|
-
const context = new llvm.LLVMContext();
|
|
7
|
-
const module = new llvm.Module(filename, context);
|
|
8
|
-
const builder = new llvm.IRBuilder(context);
|
|
9
|
-
|
|
10
|
-
const returnType = builder.getInt32Ty();
|
|
11
|
-
const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
|
|
12
|
-
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
|
|
13
|
-
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'addWithAttributes', module);
|
|
14
|
-
|
|
15
|
-
const noInlineAttr = llvm.Attribute.get(context, llvm.Attribute.AttrKind.NoInline);
|
|
16
|
-
const inRegAttr = llvm.Attribute.get(context, llvm.Attribute.AttrKind.InReg, builder.getInt32Ty());
|
|
17
|
-
func.addFnAttr(noInlineAttr);
|
|
18
|
-
func.addParamAttr(0, inRegAttr);
|
|
19
|
-
|
|
20
|
-
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
|
|
21
|
-
builder.SetInsertPoint(entryBB);
|
|
22
|
-
const paramA = func.getArg(0);
|
|
23
|
-
const paramB = func.getArg(1);
|
|
24
|
-
const result = builder.CreateAdd(paramA, paramB);
|
|
25
|
-
builder.CreateRet(result);
|
|
26
|
-
|
|
27
|
-
console.log(module.print());
|
|
28
|
-
|
|
29
|
-
if (llvm.verifyFunction(func)) {
|
|
30
|
-
console.error(`${filename}: verifying the 'addWithAttributes' function failed`);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
if (llvm.verifyModule(module)) {
|
|
34
|
-
console.error(`${filename}: verifying the module failed`);
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
}
|
package/test/bitcodeWriter.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import fs from 'fs';
|
|
2
|
-
import path from 'path';
|
|
3
|
-
import llvm from '..';
|
|
4
|
-
|
|
5
|
-
export default function testBitcodeWriter(): void {
|
|
6
|
-
const filename = path.basename(__filename);
|
|
7
|
-
const context = new llvm.LLVMContext();
|
|
8
|
-
const module = new llvm.Module(filename, context);
|
|
9
|
-
const builder = new llvm.IRBuilder(context);
|
|
10
|
-
|
|
11
|
-
const returnType = builder.getInt32Ty();
|
|
12
|
-
const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
|
|
13
|
-
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
|
|
14
|
-
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'writer', module);
|
|
15
|
-
|
|
16
|
-
const entryBB = llvm.BasicBlock.Create(context, 'entry');
|
|
17
|
-
builder.SetInsertPoint(entryBB);
|
|
18
|
-
const paramA = func.getArg(0);
|
|
19
|
-
const paramB = func.getArg(1);
|
|
20
|
-
const result = builder.CreateAdd(paramA, paramB);
|
|
21
|
-
builder.CreateRet(result);
|
|
22
|
-
|
|
23
|
-
console.log(module.print());
|
|
24
|
-
|
|
25
|
-
if (llvm.verifyFunction(func)) {
|
|
26
|
-
console.error(`${filename}: verifying the 'writer' function failed`);
|
|
27
|
-
process.exit(1);
|
|
28
|
-
}
|
|
29
|
-
if (llvm.verifyModule(module)) {
|
|
30
|
-
console.error(`${filename}: verifying the module failed`);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const outputDir = path.join(__dirname, 'temp');
|
|
35
|
-
const outputBitcodePath = path.join(outputDir, 'add.out.bc');
|
|
36
|
-
if (!fs.existsSync(outputDir)) {
|
|
37
|
-
fs.mkdirSync(outputDir);
|
|
38
|
-
}
|
|
39
|
-
if (fs.existsSync(outputBitcodePath)) {
|
|
40
|
-
fs.unlinkSync(outputBitcodePath);
|
|
41
|
-
}
|
|
42
|
-
llvm.WriteBitcodeToFile(module, outputBitcodePath);
|
|
43
|
-
console.log(`${filename}: bitcode was successfully written to the ${outputBitcodePath}`);
|
|
44
|
-
}
|
package/test/class.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import path from 'path';
|
|
2
|
-
import llvm from '..';
|
|
3
|
-
|
|
4
|
-
export default function testClass(): void {
|
|
5
|
-
const filename = path.basename(__filename);
|
|
6
|
-
const context = new llvm.LLVMContext();
|
|
7
|
-
const module = new llvm.Module(filename, context);
|
|
8
|
-
const builder = new llvm.IRBuilder(context);
|
|
9
|
-
|
|
10
|
-
const elementTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
|
|
11
|
-
const classStructType = llvm.StructType.create(context, elementTypes, 'Person');
|
|
12
|
-
|
|
13
|
-
const returnType = builder.getVoidTy();
|
|
14
|
-
const paramTypes = [llvm.PointerType.getUnqual(classStructType)];
|
|
15
|
-
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
|
|
16
|
-
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'class_Person_constructor', module);
|
|
17
|
-
|
|
18
|
-
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
|
|
19
|
-
builder.SetInsertPoint(entryBB);
|
|
20
|
-
|
|
21
|
-
const thisPtr = func.getArg(0);
|
|
22
|
-
const propertyPtr = builder.CreateGEP(classStructType, thisPtr, [
|
|
23
|
-
builder.getInt32(0),
|
|
24
|
-
builder.getInt32(1)
|
|
25
|
-
]);
|
|
26
|
-
builder.CreateStore(builder.getInt32(111), propertyPtr);
|
|
27
|
-
builder.CreateRetVoid();
|
|
28
|
-
|
|
29
|
-
console.log(module.print());
|
|
30
|
-
|
|
31
|
-
if (llvm.verifyFunction(func)) {
|
|
32
|
-
console.error(`${filename}: verifying the 'class_Person_constructor' function failed`);
|
|
33
|
-
process.exit(1);
|
|
34
|
-
}
|
|
35
|
-
if (llvm.verifyModule(module)) {
|
|
36
|
-
console.error(`${filename}: verifying the module failed`);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
};
|