![require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages](https://cdn.sanity.io/images/cgdhsj6q/production/be8ab80c8efa5907bc341c6fefe9aa20d239d890-1600x1097.png?w=400&fit=max&auto=format)
Security News
require(esm) Backported to Node.js 20, Paving the Way for ESM-Only Packages
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
a js llvm library
For 'tis the sport to have the enginer
Hoist with his own petar'...
- Hamlet, Shakespeare
Frustrated with the state of JS support for LLVM, I built another library. Rather than trying to be generic bindings to libLLVM, petard tries to make the most common case easy: generating fresh IR. You don't have total control over the LLVM machinery and there aren't really facilities for working with IR that already exists (so you can't write passes), but if those limitations aren't a problem petard makes dealing with LLVM much simpler.
This software is under active development. The README should reflect current functionality, but don't be surprised if something you think should work causes your computer to segfault. petard aims to catch these things and throw JavaScript errors, but we don't have very good coverage yet. Please do submit a ticket or pull request if there's a type of programmer error that could be caught earlier and an error thrown.
one more warning: it is currently VERY leaky. don't use in any program that will be running very long.
First you need to install LLVM version 3.6 on your system, including the dev libs. Look to the Travis build config for details.
when you're building petard you will need to set the environment variable
LLVM_CONFIG
to be the llvm-config you've installed. For example, if you're on
Ubuntu where it's isntalled as llvm-config-3.6
, you'll enter:
> LLVM_CONFIG=llvm-config-3.6 npm run build
or
> LLVM_CONFIG=llvm-config-3.6 npm install petard
Once you've got it built successfully, try this:
llvm = require 'petard'
{i8, i32, pointerTo} = llvm.type
hello = llvm.CodeUnit "hello"
main = hello.makeFunction "main", i32
puts = hello.declareFunction "puts", i32, pointerTo i8
text = hello.constant "Hello, world!\n"
message = main.loadConstant text
main.callFunction puts, message
main.return 0
hello.writeBitcodeToFile "hello.bc"
Then use opt and clang as usual with the LLVM IR bitcode file. Look at the example folder for more examples.
Alternatively, you can JIT compile and call the function from JavaScript.
hi = hello.makeFunction "hi", i32, pointerTo i8
prefix = hello.constant "Hello, "
hi.callFunction puts, hi.loadConstant prefix
hi.callFunction puts, hi.parameter 0
hi.return 0
greet = hi.jitCompile()
greet "Bill"
greet "Janice"
greet "Bart"
The underlying C++ API exposes the basics of LLVM IR construction, and the node wrapper adds some higher-level functionality on top of that. In the listing the methods in JavaScript are marked with a (js).
Represents an LLVM type. You'll see these most commonly when you get them from
petard.type
and pass them when constructing functions and values. The only
thing you can do to a type is get its name as a string.
Returns the type as a string.
Represents an LLVM value, or if you look at it another way, represents an abstract expression. You'll get these and pass them in to many of the builder methods. The only thing you can do to a value is get its type.
A property containing the type of the value.
Something that can construct LLVM IR. It represents a particular part of a function (an LLVM block) as well as a cursor within that block where instructions will be placed. Calls to builder methods construct LLVM IR and take and return values and other builders.
Return from the function. If a value is provided, it is the return value of the function. You must ensure that the value passed is of the same type as the return type of the function.
Reference function parameter index
.
Perform pointer math on the aggregate type pointer to produce a new pointer to the given structure member. For details, see the GetElementPointer FAQ.
Extract the element at the specified index from the vector.
Insert the value as the element at the specified index from the vector.
Load a constant value. Currently the only usage is to load a string constant, see the first example.
Call the given internal or external function, passing in the parameter values.
Allocate space the size of type on the stack. If an arraySize is provided, instead allocate that much space times the arraySize. Returns a pointer value to the space.
Load a value from the memory pointed to by pointer.
Store the value in the memory pointed to by pointer.
Add the values. Works on integer and float values.
Subtract the right value from the left. For integers and floats.
Multiply the values. They can be integers or floats.
Unsigned integer divide the left value by the right.
Signed integer divide the left value by the right.
Floating point divide the left value by the right.
The remainder when the left value is unsigned integer divided by the right.
The remainder when the left value is signed integer divided by the right.
The remainder when the left value is floating point divided by the right.
Bitwise and the values.
Bitwise or the values.
Bitwise xor the values.
Shift the left value left by the right value number of bits.
Shift the left value right logically (sign-ignoring) by the right value number of bits.
Shift the left value right arithmetically (sign-preserving) by the right value number of bits.
Compare the values for equality.
Compare the values for inequality.
Unsigned greater than comparison.
Unsigned greater than or equal to comparison.
Unsigned less than comparison.
Unsigned less than or equal to comparison.
Signed greater than comparison.
Signed greater than or equal to comparison.
Signed less than comparison.
Signed less than or equal to comparison.
Float value ordered equality comparison.
Float value ordered inequality comparison.
Float value ordered greater than comparison.
Float value ordered greater than or equal to comparison.
Float value ordered less than comparison.
Float value ordered less than or equal to comparison.
Float value unordered equality comparison.
Float value unordered inequality comparison.
Float value unordered greater than comparison.
Float value unordered greater than or equal to comparison.
Float value unordered less than comparison.
Float value unordered less than or equal to comparison.
Truncate the integer value to a smaller type.
Zero extend the integer value to a larger type.
Sign extend the integer value to a larger type.
Convert the floating point value to an unsigned integer.
Convert the floating point value to a signed integer.
Convert the unsigned integer value to a floating point.
Convert the signed integer value to a floating point.
Truncate the floating point value to a smaller type.
Extend the floating point value to a larger type.
Convert the pointer to an integer type.
Convert the integer to a pointer type.
Cast the value to another type without changing the bits.
Non-branching value select. Returns the value corresponding to the ifTrue value if the condition is true, and the ifFalse value if the condition is not true. Also operates on vectors.
Construct a new LLVM value of the given type for the given JavaScript value.
Builds the if conditional control structure for the given condition. Returns an object with then and else properties, each builders for the then and else blocks.
with Value BuilderCallback(Builder condition)
Builds the while loop control structure. The callback should take a builder for the loop condition and should return the condition value. Returns a builder for the body of the loop.
Unconditional branch to the target.
Conditional branch. If the condition is true, branch to the ifTrue builder, otherwise branch to the ifFalse builder.
Multi-way branch. If none of the cases added to the returned switch builder match the value of the condition, control follows the defaultDest.
Builds the switch control structure. While the switch
method simply produces
a multi-way branch, this provides the high-level control you're expecting
out of the box, namely merging back to one place at the end.
Create another block in the same function. Use with the branching instructions
to create custom control structures. See the node wrapper for examples on
using createBlock
, splitBlock
, useBlock
, insertBefore
, insertAfter
,
and br
to build control structures.
Split the current block at the cursor. The object itself retains the top half (all the instructions written before) and the returned builder takes the bottom half (all the instructions written after). In practice this usually means the terminator of the block is the only instruction in the new block.
Set this builder to start building in the target block. Make sure this builder already has a terminator or you'll get into trouble.
Start inserting instructions after the cursor rather than before. Mainly useful to appending a terminator to a block ahead of time.
Resume inserting instructions before the cursor, the default behavior. Used to restore the standard mode after inserting a terminator.
A specialization of a builder corresponding to a complete function. In addition to the normal builder methods, it has a few special properties.
A property containing the name of the function.
A property containing the type of the function.
JIT compile the function, the set up a foreign-function interface to make the function callable from JavaScript. Uses the ffi library to dynamically bind the functino pointer.
A special tool for working with switch statements. It is returned from the switch method of a builder.
Adds a case for the value onVal
, branching to target.
The same thing as the switch builder, but for choose statements.
The default case builder.
Adds a case for the value onVal
, returning a builder for the case.
Represents an overall unit of code, such as a file. Directly corresponds to an LLVM Module. It has a few helpful methods.
Compile a constant value into the IR. At the moment the only use is to load a constant string. See the first example for usage.
Declare a function external to this code unit that will be linked in. Takes the name of the function and optionally the return type and parameter types. Returns a special FunctionValue.
Create a new function in this code unit with the given name and optionall the return type and parameter types.
Dump the code unit IR to the screen. Useful for debugging, not so much for regular usage, since the underlying LLVM method always dumps to stderr.
Write the bitcode for this code unit to a file with the given filename. The file must not exist, if it does this method will fail.
JIT compile the function. Returns the raw pointer to the function as a Buffer. You may find the corresponding helper method on FunctionBuilder to be more useful since you can call the result of that method from JavaScript.
type
dictThis dict contains all the basic types for easy reference.
i1
- A one bit integer (a boolean).i8
- A single byte.i16
- A small word.i32
- A medium word.i64
- A long word.f16
- A half-precision floating point value. (LLVM's half
)f32
- A single-precision floating point value. (LLVM's float
)f64
- A double-precision floating point value. (LLVM's double
)FAQs
a js llvm library
The npm package petard receives a total of 0 weekly downloads. As such, petard popularity was classified as not popular.
We found that petard demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
require(esm) backported to Node.js 20, easing the transition to ESM-only packages and reducing complexity for developers as Node 18 nears end-of-life.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.