#Nexirol&Renirol
1 messages · Page 2 of 1
ah yes
₵Ʉ฿Ɇ
that's
a bit better
also a lot more epileptic
... why did the first two faces work and none of the other ones 
and the second one is backwards because ofc, why wouldn't it be
use the debugger
Check your winding order
there is
a lot more wrong here than just winding order 
yes because its obvious
just posting random renderdoc shots doesnt fix it
I-
am using a debugger
and i mean debugger debugger
add vertex colors
and shade each face in a different color, makes it easier to visually debug shit
ya do realize I'm not posting it here for solutions, right?
you never specified you weren't 
this is my thread
I can post whatever issues I want 
MemoryUtil.memCopy(
MemoryUtil.memAddress(faces[i].fb),
fb + i * (faceStride), faceStride
);```also like
debugger kinda doesn't help with java when I'm dealing with native memory
which, I'mma not do that for right now 
ok now next thing is colors
next problem: each face has a different vertex order
a UV cube
actually don't think I've ever made one of these
actually the negatives were wrong
BoxMesh mesh = new BoxMeshBuilder()
.withElement(3)
.withElement(4)
.withElement(2)
.withSize(1, 1, 1)
.allFaces()
.colors(
0, 0, 0, 1,
1, 0, 0, 1,
1, 1, 0, 1,
0, 1, 0, 1
)
.uvs(
0, 0,
1, 0,
1, 1,
0, 1
)
.build();```
this is an abomination
but hey at least I don't need like 5 constructors for box meshes!
this abomination can do all the box meshes I will need!
including this one which only has positive faces```java
BoxMesh mesh = new BoxMeshBuilder()
.withElement(3)
.withElement(4)
.withElement(2)
.withSize(1, 1, 1)
// .allFaces()
.emitFace(true, 0)
.emitFace(true, 1)
.emitFace(true, 2)
.colors(
0, 0, 0, 1,
1, 0, 0, 1,
1, 1, 0, 1,
0, 1, 0, 1
)
.uvs(
0, 0,
1, 0,
1, 1,
0, 1
)
.build();```
noice
BoxMesh mesh1 = new BoxMeshBuilder()
.withElement(3).withElement(4).withElement(2).withSize(10, 1, 10)
.emitFace(true, 0).emitFace(false, 0).emitFace(true, 1).emitFace(false, 1)
.colors(1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1)
.uvs(0, 0,
10, 0,
10, 1,
0, 1)
.buildFace(true, 2)
.colors(1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1)
.uvs(0, 0,
10, 0,
10, 10,
0, 10)
.finishFace()
.buildFace(false, 2)
.colors(1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1,
1, 1, 1, 1)
.uvs(0, 0,
10, 0,
10, 10,
0, 10)
.finishFace()
.build();```I think it is obj, gltf, and scene loading time after I add normals
normals 
public static ShaderProgram FLAT = new ShaderProgram(
ShaderAttachment.of(GL20.GL_VERTEX_SHADER, FileUtils.readCL(Main.class, "flat_shader.vsh")),
ShaderAttachment.of(GL20.GL_FRAGMENT_SHADER, FileUtils.readCL(Main.class, "flat_shader.fsh"))
);```created a second constructor a bit ago which takes `ShaderAttachment`s which does the stuff with the Shader class behind the scenes
🤷 basically the same thing, but it abstracts away having to deal with closing the `Shader` instances
how is the glb larger than the gltf
3dviewer cannot handle deccer's cubes 
(reason: 3dviewer does not support nearest neighbor sampling)
3d viewer tooo
thanks microsoft
you can hide that attachment bs from the public interface, only the shaderprogram needs to do shader magic using the 2 strings you pass down
ok but
geometry, tessellation, and mesh shaders all exist
And I don’t want to have overload constructors for each combination of them 
and the shader attachment thing isn’t that annoying, so I don’t really care to make a less generalized constructor
you can ignore geometry and tessellation
the attachment thig is realy annoying when you dont even need to use it as a consumer of your api
but its just the first iteration, so its, fine, you can refactor stuff later, or rewrite the whole thing
It pains me to observe the amount of time spent worrying about code structure instead of making progress on drawing pixels.
Having said that you’re already drawing deccer cubes and I am nowhere close to that
So I should be quiet, have fun navel gazing your classification systems
Looking great though
I’ve done this several times, so uh
yeah I’m gonna focus on code structure, ‘cuz that keeps ending up being a problem
I fail to see how it’s annoying
It just tells the code hey I want you to load this shader as a fragment shader
mr. deccer may I inquire what deccer cubes are
I have not drawn deccer cubes yet
I think I need a gltf loader impl 
(aka an impl of assimp)
Ok so I think
- gltf
- scene loading
- data driven shader stuff (hey look something that will make developers not have to even know ShaderAttachment exists)
- resume learnopengl
So for my terrain object impl
… I kinda wanna support caves out of the box
Like actually have a feature for that
what happened to loading gltfs
I’m thinking ahead to features that will come after it
You can always rewrite and refactor, sometimes thinking ahead takes longer than actually implementing the features
Aware
But this feature is sorta one of the large reasons I want my own game engine; making caves in like…
UE4 or godot or unity is a massive pain
And caves are sorta a large plot point of the game I wanna make
so either, voxels or just mesh and then embedded into terrain
probably voxels smoothed out using surface nets, the somehow connected to be flush with the terrain
anyway, time to start looking at assimp
that is a bizzare name for a library imo
https://learnopengl.com/Model-Loading/Mesh
wow look, nothing that is useful to me 
just data structures
which I can deal with on my own, designing them around what I need
Assimp::Importer does not seem to exist in the lwjgl bindings
skill issue again
AIScene scene = Assimp.aiImportFile(buffer, flags);
apparently lwjgl translated it to this
... first time I've seen lwjgl 3 stray away from the library that it was creating bindings for
that's
confusing and annoying
its literally the same api 🙂
Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(path, aiProcess_Triangulate | aiProcess_FlipUVs);
AIScene scene = Assimp.aiImportFile(buffer, flags);
ah yes because ReadFile is the same words as aiImportFile
lwjgl usually has a 1:1 match on the names
although
maybe it's not the same thing
https://github.com/jvm-graphics-labs/learn-OpenGL/blob/master/src/main/kotlin/learnOpenGL/common/Model.kt
apparently this guy has a more direct binding of assimp???
compile 'com.github.kotlin-graphics:assimp:1be72df603febc1b6b22dd5c7085af12aa1a832b'
h
unable to open file
prints the entire file's contents
GLTF: could not open referenced file "SM_Deccer_Cubes.bin"
wh
oh yeah that makes sense ig
... so I suppose I'm not gonna be able to load deccer cubes from RAM with assimp, huh? (Like without writing it to the disk)
what?
deccer cubes requires a few extra files that aren't embedded into the gltf
so assimp then tries to find those on the disk, but can't because the files aren't in the working dir, since I'm trying to load stuff from memory instead
and that's a gltf loaded
I don't really
want to require the resources to be extracted
I like stuff being able to be done entirely in memory
so you're going to read a file from disk to memory to read it?
Im not quite sure I understand what you're saying here
basically
my file can be in a zip file
Assimp assume it is either in RAM or on the disk (as far as I know, compressed in a zip file does not count)
if it is in RAM, the file must either have no dependencies or have those dependencies extracted to the disk ahead of time
I do not want to extract files at all if I don't have to, but deccer's cubes have a dependency file (SM_Deccer_Cubes.bin in the case of the deccer's cube file I was trying to load)
so Assimp would automatically look for it in the working directory, where it was not located
and the working directory cannot be set inside of a zip file
if you're not constantly updating the mesh its not a problem
I've seen multiple programs cripple themselves in this sorta assumption
(granted, most of them are zip manipulation utilities and such)
doing like a single funny thing with zip operations can make a program take like 5* as long to run
and like
most of the time it's not even difficult to not do said funny thing
deccer just vanished from the thread?
... why is this an int buffer?
/** * Specifies the number of components for a given UV channel. * * <p>Up to three channels are supported (UVW, for accessing volume or cube maps). If the value is 2 for a given channel n, the component {@code p.z} of * {@code mTextureCoords[n][p]} is set to 0.0f. If the value is 1 for a given channel, {@code p.y} is set to 0.0f, too.</p> * * <p>Note: 4D coordinates are not supported.</p> */
... okay?
then why is it a 2d array?
wait no
why is it 8 elements
this is as far as I can currently go with GLTF
learn opengl doesn't do lighting in compute or post
nMap = pow(abs(nMap), 0.5) * sign(nMap);
wh-
Warning, (version, profile) forced to be (110, compatibility), while in source code it is (330, core)
ERROR: #version: versions before 140 do not allow a profile token
ERROR: 0:17: '' : syntax error, unexpected IDENTIFIER
ERROR: 2 compilation errors. No code generated.
why does that cause this
regardless; normal maps approximately applies without using tangents and binormals
temporary workaround for the fact that I do not have tangents and binormals 
also looking at this with specular on is making me think of voices of the void
oh hey, assimp just casually provides me with tangents and bitangents
guess that's a good next thing to hook up 🤷
SimpleRenderState state = new SimpleRenderState();
state
.withTexture(textures.get(2), 0)
.withTexture(textures.get(1), 1)
.withTexture(textures.get(0), 2)
.withTexture(textures.get(3), 3)
.withSetup(() -> {
ShaderPrograms.PBR_SHADER.uniformInt(
"textureMaps", 1 | 2 | 4 | 8
);
ShaderPrograms.PBR_SHADER.uniformInt("ambient", 1);
ShaderPrograms.PBR_SHADER.uniformInt("normalMap", 2);
ShaderPrograms.PBR_SHADER.uniformInt("specularMetalic", 3);
});```this should also be abstracted away 'cuz it's a bit ugly ~~and also using hardcoded constants that aren't guaranteed to be the case for all models~~
ah yes the bee is like 700* as large as the dragon
the bee is actually only ~17.5 times the size of the dragon, apparently
which is a difference of 1,400 units vs 80 units
how exactly
is a colored ambient occlusion map supposed to be interpreted?
3d viewer seems to just be looking at .r
is-
this like a screenspace AO approximation system?
looking closer it seems like that's probably what it's supposed to be?
can't tell
👋
https://github.com/GiantLuigi4/ralux
just made public the repo for the lang I plan to port to
https://github.com/GiantLuigi4/ralux/blob/master/src/test/resources/fl.java
test classes were written with java extension but it's not quite the java syntax, and I may also stray a bit further away later on
there's a few things that pass as valid that are just bizarre to see in prog langs in general 
https://github.com/GiantLuigi4/ralux/blob/master/src/test/resources/gcd.java
https://github.com/GiantLuigi4/ralux/blob/master/src/test/resources/sh.java
these files show some of the less java parts of the syntax
my problem is that I like the java syntax too much and I can't get rid of it 
if (str0 .= str1) {
also due to me not entirely liking operator overloads
custom operators may or may not be a thing at some point
for now, hardcoded special ones that redirect to functions
Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: LLVM.dll
excuse me lwjgl
but how am I supposed to provide a file that I can't even find on the internet?
like I literally cannot find anything about LLVM.dll
closest I can find is LLVM-C.dll, which lwjgl is not happy with linking against
even though it seems like it's also supposed to link against LLVM-C in addition to LLVM
oh interesting
I might go for a modified mockup of blender’s walk camera controls as the default for my game engine
"default" 
I am only implementing one camera control scheme for my editor’s camera
So more like just "the camera controls"
https://github.com/bytedeco/javacpp-presets/tree/master/llvm
ok I found something that does work
Thinking of using abi as the keyword to indicate C/C++ calls
Result: 5.0
local var0 = 5
return var0```
to learn LLVM
I'm making an LUA->LLVM JIT compiler
*and it's going pretty smoothly so far*
only caused like 5 segfaults or so so far
maybe 10
nice
Godspeed brother, llvm is a stinking hot pile of shit
oop
wrote something llvm wasn't able to properly optimize with my configuration of passes
running my passes twice makes LLVM fully optimize it
local varE = 5 + 3
local varE = varE + 6
for i=5, 10, 1 do
local varE = varE + 1
end
if varE <= 5
then
local varE = 0
elseif varE >= 20
then
local varE = 2.5
for i=5, 10, 1 do
local varE = varE + 1
for i1=5, 10, 1 do
local varE = varE + 1
end
end
end
return varE```the (partially inaccurate) LUA code that generated that IR
currently my compiler crashes if you don't write local due to me not having global variables yet, and instead local variables act as globals 
ig actually only semi-globals
eh yeah globals
had to think about how LUA works for a bit there
Do you not have FIFO scopes yet?
I'm sorta just loading everything as longs and casting to the proper data type afterwards because
- LLVM will optimize it for me
- the LLVM bindings I'm using don't seem to support loading doubles and floating point numbers

- it's easier
I do not have any kind of scoping yet
my compiler's code flow is made with it in mind
it's just not in yet
Keep a global array of scope
When you go in a scope append
When you go out of scope pop
yeah I'm aware of how scoping works 
global = {'print': <external_function>}
scope_0 = {}
global['var0'] = 5
scope_0['var1'] = 2
global['var'] = global['var0'] * scope_0['var1'] * global['var0'] + scope_0['var1'] * global['var0']
global['func0'] = function
global['func1']()
end
global['func1'] = function
global['print']("test")
end
global['print']("a")
global['func0']()```there's uh
also this
var0 = 5 var1 = 2
var = var0 * var1 * var0 + var1 * var0
function func0()
func1()
end
function func1()
print("test")
end
print("a")```lua equivalent of that
I had to rewrite the entirety of my lexer as a state machine because I didnt implement scopes early :D
if you call func0 before the line where func1 is defined, LUA will throw an error du to func1 not being defined yet
but if you call func0 after the line of func1, it'll run fine
functions are defined as they come in the file, when they come in the file
my compiler is also single pass, as is the actual LUA compiler
no AST to be found here
Is this actually true? Why does it support out of order declarations and then not support them
well it kinda™️ supports them
it supports them if you call the function that calls the other function after the other function is defined
it doesn't really validate whether or not functions exist at compile/parse time
just sorta a quirk of how the interpreter works
(LUA is designed in a way where it actually is sorta easier to not deal with an AST)
the structure of my compiler actually resembles that of an AST parser too
https://github.com/GiantLuigi4/jlluavm/blob/master/src/main/java/tfc/jlluavm/parse/LUASyntaxConsumer.java
I'll deal with it tomorrow after I deal with else
it's currently midnight for me, and loops and if/elseif/elses are sorta the first things in LUA's syntax I can even begin to test scoping with, and are also the most recent things I've implemented 
before now has just been arithmetic stuff
unironically
I'm finding this fun so far
I kinda fear trying to link this stuff to JNI functions though 
(I'm gonna want this to be able to call java code at some point)
probably gonna like
runtime compile a module to just get the addresses of the necessary functions
and then literally just hard embed those addresses into the IR and cast them to functions, then call then
LLVM ERROR: MCJIT::runFunction does not support full-featured argument passing. Please use ExecutionEngine::getFunctionAddress and cast the result to the desired function pointer type.
apparently I can't use LLVM to run functions that take 64 bit integers as parameters
incredible
welp I guess I need a metacall function thing... or something
long result = JNI.invokePP(Double.doubleToLongBits(20), LLVM.LLVMGetFunctionAddress(engine, functionEntry.getName()));
eh this works...
for now
won't work in the long run
there's actually a really funny thing I can do with JNI and LLVM
where I generate a class at runtime (synthetic class), have it have a native method that takes in the required arg types, and bind it to the function I generate using LLVM
and call it using either method handles or jni
local varE = !0 + 3
local varE = varE + 6
for i=5, 10, 1 do
local varE = varE + 1
end
if varE <= 5
then
local varE = 0
elseif varE >= 20
then
local varE = 2.5
for i=5, 10, 1 do
local varE = varE + 1
for i1=5, 10, 1 do
local varE = varE + 1
for i2=5, 10, 1 do
local varE = varE + 1
end
for i2=5, 10, 1 do
local varE = varE + 1
end
end
for i1=5, 10, 1 do
local varE = varE + 1
for i2=5, 10, 1 do
local varE = varE + 1
end
for i2=5, 10, 1 do
local varE = varE + 1
end
end
end
end
return varE```broke my compiiler 
actually I think this might have to do with scopes
so, scoping time
yeah, it's scopes
scopes are now in; next thing is to update how local behaves to make it accurate to LUA
which took, very little time to setup 
this seems to be the best I can get out of LLVM's optimization passes for this extremely cursed LUA file
~63-73 ms vs ~65-75 ms
(data sorta inaccurate, since I'm kinda excluding outliers)
optimization pass collection seems to shave off ~2ms
... though I don't think this data is accurate at all, considering I don't think executing arg0+3+6 should take longer than optimizing asm code that is more complex than that
jni linkage moment
4.7, 4.9, 6.9, 4.5, 5.4, 3.9, 5.2, 4.5
5.5, 5.8, 6.5, 4.1, 5.7, 5.9, 5.0, 4.0
ok, around 1ms
I think there might still be some JNI overhead or something going on there but that's close enough of a metric I think
and my code outputs 17, just as it should
https://github.com/GiantLuigi4/jlluavm/blob/master/src/test/resources/perfhog.lua
I love compiler test files
(this takes 14 seconds to run with optimization passes, 115 seconds to run without)
https://github.com/GiantLuigi4/jlluavm/blob/d8d43efe9407872693b712e974b32946231d0f43/src/main/java/tfc/jlluavm/parse/LUASyntaxConsumer.java#L344-L399
actually it throws an error without
115 seconds is the bare minimum optimization passes for it to not throw an error
ok so
I need to uh
port this to llvm ir builder
%struct.JNINativeInterface_ = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr }```
I-
what the heck
feels like an AI went rogue to generate that
oh ofc it compiled for 32 bit
Exception in thread "main" java.lang.NoSuchMethodError: LMyJavaClass;.nativeMethod(Ljava/lang/Class;Ljava/lang/String;Ljava/lang/String;)J
lol what
ah right, static and non-static are different id get methods
2227764525016
okay
so... this is what I need to port to IR builder
... why are there so many ptrs 
ok Og makes this a bit more sane to look at
what's happening
I’m making adventures into compiling LUA for sake of learning LLVM compiler infrastructure so that I don’t have to learn it in my ralux project
Fun!
… that struct is composed of 234 pointers
Of which I need 170 (release chars utf), 113 (get method id), and 169 (get chars utf)
LLVMValueRef envRef = LLVM.LLVMGetParam(builder.function, 0);
LLVMValueRef alloca = LLVM.LLVMBuildAlloca(root.builder, jniEnv.type(), "envptr");
LLVMValueRef env = LLVM.LLVMBuildLoad2(root.builder, jniEnv.type(), envRef, "envro");
LLVMValueRef why = LLVM.LLVMBuildStore(root.builder, env, alloca);
PointerPointer<LLVMValueRef> params = new PointerPointer<>(2);
params.put(0, root.loadLong(0));
params.put(1, root.loadInt(169));
LLVM.LLVMBuildInBoundsGEP(
root.builder, alloca,
params, 2,
"llvm_is_being_dumb"
);```after literally like an hour trying to get this one call to work I randomly decided to stop using my abstraction
... for some reason doing that made it work
even though behind the scenes I'm pretty sure it's the same thing
ok well time to translate it back to my abstraction
... and now it just works
without even doing anything dumb (such as pointlessly boxing and unboxing the pointer)
no idea what changed
LLVMValueRef nameChr = root.call(freeUTF, envRef, nameJSTR, jniFalse);
now this is giving me problems
0
incredible (this is very much so NOT the right value at all)
actually I think I might know what's going on here
maybe not
ok tracked down an older version of LLVM to get a nicer IR
and hey
I actually have information now!
this older version of llvm generates much nicer IR (for readability, at least)!
; Function Attrs: nounwind uwtable
define dso_local dllexport i64 @Java_MyJavaClass_nativeMethod(
%struct.JNINativeInterface_** %env_ptr,
%struct._jobject* nocapture readnone %1,
%struct._jobject* %2,
%struct._jobject* %3,
%struct._jobject %4*
) local_unnamed_addr #0 {
%env_loaded = load %struct.JNINativeInterface_*, %struct.JNINativeInterface_** %env_ptr, align 8, !tbaa !3
%getUTF = getelementptr inbounds %struct.JNINativeInterface_, %struct.JNINativeInterface_* %env_loaded, i64 0, i32 169
%getUTFLoaded = load i8* (%struct.JNINativeInterface_**, %struct._jobject*, i8*)*, i8* (%struct.JNINativeInterface_**, %struct._jobject*, i8*)** %getUTF, align 8, !tbaa !7
%9 = tail call i8* %getUTFLoaded(%struct.JNINativeInterface_** %env_ptr, %struct._jobject* %3, i8* null) #1```ok so now I need to recreate this
and if I can do that
I should actually have a functional file
140709365796720
yes
I have done it
I have called a jni method without segfaulting
next step: use jni
ProtoJNI.init();
System.out.println(ProtoJNI.getJNIEnv());
System.out.println("MID");
long methodID = ProtoJNI.getStaticMethodID(Test.class, "print", "(Ljava/lang/String;)V");
System.out.println(methodID);
ProtoJNI.callStaticVoid(ProtoJNI.class, methodID, "Hello!");```
> 140708482422784
> MID
> 2138686952888
> Hello!
LLVM's optimization passes agree with my code, other than the lack of alignments
and lack of tail call
pretty sure this is also more optimal than O3
is this llvm lua thing going to render triangles
well
if I get it hooked up to computer craft like I want to, I can then add on tom’s perhiperals to get a software implementation of like GL11 or something (no direct hardware access, unfortunately)
But this llvm lua thing is mostly just a learning project for a bigger project that will be used for drawing triangles
what are computer craft and tom's perhiperals
Minecraft mods
Computer Craft is a mod that adds computers that can be programmed with LUA
Toms Perhiperals adds a monitor block (with connection, so you can make big monitors) and a scuffed opengl implementation for rendering purposes
It uh
Doesn’t do depth clipping with the near plane last I saw it, so it can’t really be used for first person stuff 
(I do not really use computer craft ever myself; someone mentioned compiling computer craft scripts and I decided hey that’d probably be a good way to learn LLVM IR)
are you also active on the minecraft mod discord?
Which one?
There are many minecraft mod discords
There are a large number of mod authors who have their own discord server (or servers)
There are probably several general modding servers
There’s probably several general mod pack dev servers
There’s also probably several general mod dev servers
?
I don't know anything about them, just I imagined there must be one
I’m active on a few
mostly just in the communities on them though, and they’re the servers owned by certain devs; not for just general modding
Sometimes in life
You try to say something meaningful
Then realize you broke the functionality of loops as a syntax feature while doing so
git logs are fun when they tell a story
he did infact not break loops
you have your own minecraft mod discord
mhm
I’m confused why loops didn’t explode

it works and I don’t know why and this concerns me
So at this rate
It’ll be like a week till I get stuff polished enough for me to begin implementing functions
since I kinda wanna get all the type coceriencio coercion weird word properly implemented first
And that’s talking calling JNI functions, not defining functions using LUA’s syntax
Actually an LUA based dependency management system sounds fun
that's awesome
I would be curious about your lua deps management system
I like lua
I used it in blockens
Basically
In java
We have this tool called gradle
It’s what a lot of java devs use for dependency management and as a build system
But a lot of people sorta treat it like a black box and don’t like to work with it
Personally, I’m a fan of it because I can actually script it to automate tasks
But it’s slow as heck and not easy to figure out how to do complex stuff with it
My way of learning LUA
was programming a graphing calculator
Which used TI BASIC, not LUA
but it had the if then end thing going on like LUA has so close enough tbh
I stand corrected
either later today or tomorrow should be when I start doing that
nice
LLVM ERROR: Cannot select: 0x18d2bd1a798: i64 = bitcast Constant:i8<116>
0x18d2bd1b0f0: i8 = Constant<116>
In function: $$module_lua_jit_$root_entry$_tfc.jlluavm.parse.LUASyntaxConsumer5ae9a829
I broke LLVM
Lyzantra
Compile Error! Click the
reaction for more information.
(You may edit your message to recompile.)

So is this like
Going to just be a thing from now on when using block quotes?
test
test
test
heuh?
Bjorn, thanks for reminding me of 
Might be a while till I give another status update; got into the groove of working on mcef&webdisplays again https://cdn.discordapp.com/attachments/1138546227743567902/1297018251359817788/2024-10-18_22-06-28.mp4?ex=67150ea0&is=6713bd20&hm=19f42dc7adf1a2789a56c0f50b2fa1e5366fb71fc87e0f31bab2057ece04fccd&
(Clip from me working on optimizing display logic)
As far as I know
I have two options for optimizing this further:
- go modify CEF itself to keep its buffers in consistent locations because it does not seem to do that, which is… absolutely bizarre to me
- go modify JCEF to make it support OnAcceleratedPaint and figure out context sharing (more viable option)
… I am now under the impression I would have to modify chromium to do that first one and I’m finding people saying that onacceleratedpaint has been removed and can find barely any info on it
CEF and JCEF are dependencies of MCEF
MCEF is not a project I own, but it is one I work on
this is a browser in a minecraft plugin?
I didn't realize this was minecraft related
is minecraft just like an operating system now
mod, not plugin
plugins exist only on the server, mods exist on both client and server
I just play vanilla minecraft, I have never once installed a minecraft mod
it's like this alternative universe of minecraft that just is not all interesting to me, minecraft doesn't need any mods imo
and it's just all this unecessary stuff that doesn't make the game better or more interesting
I mean some of the early popular mods had a ton of automation
but now...a browser mod
cool
I already have a browser, I didn't need minecraft to have one
it's just people showing off I guess
idk your fun isn't wrong, it's just not making minecraft a more fun game though
imo anyway
people should use all that pretty amazing talent and time to build something that's theirs and exist external to minecraft that people will actually use because it doesn't exist in minecraft and people don't want to use a browser in minecraft
like it's almost like minecraft mods are blackhole, a virus, that captures talented people and consumes all the value that they might have improved people's lives with
instead it just goes into a fucking meme that might get some attention on minecraft forum
anyway
+1 cool, very impressive stuff
my ears have been assaulted today
I mean
both of these have 700k (or more) downloads
because people want to be able to display content in game and watch youtube with eachother and stuff
from within a game
now what is a meme
is the fact that at some point I was working on a smart watch mod
I asked my daughter if she would do that, she plays a lot of roblox and minecraft and she didn't know it existed but she said it sounded cool
just now
idk ok I guess it has value, there are lot of kids playing minecraft
sorry lol
^ there is genuinely no real purpose to this 
also this item can add actual gameplay value
you know, alt tab is a thing
yeah I use alt tab like every 5 seconds
also, I'm quite literally having to work on a modified version of JCEF in order to make this mod
I think ds58 might've actually refered to the gmod one while making the mc one, not exactly sure though
studio execs should consider if modders haven't added a chrome browser to their "successful" game, was it really successful?
lol
https://github.com/CinemaMod/webdisplays/tree/audio-handler/src/main/java/net/montoyo/wd/client/audio
I tried so hard to find something to reference for this and found absolutely nothing
A Minecraft mod for creating and interacting with web browsers - CinemaMod/webdisplays
like I don't think I've ever googled so much for a single thing in my entire time that I've been writing code
jcef doesn't even support audio handlers, I had to go implement that in C++
mc modding is sorta just
you're given this massive toolbox that is really easy to use
you don't have to use it, but using it makes your life far easier and reduces the odds of incompatibilities
so if you wanna go learn something, you can just spin up a minecraft dev env and ignore whatever parts of the toolbox you don't want to use and use whatever ones you want for convenience sake
or if you wanna make something that you plan to release, you can choose as much as the toolbox as you want
sure, that's true
ok so on my LUA compiler
I think I've actually reached a point where it would be easier for me to start making a compiler for my own language, to force myself to get up a good wrapper for LLVM and force myself to figure out GEP and stuff
That’s such a boring solution though
patch jni yourself
Oh no you missunderstand
The program is segfaulting when I try to call JNI
And I think this is because of strings but I’m not actually sure
So I kinda wanna get an actual thing going that will compile stuff properly and such
write it in c
That’s a boring solution and does not teach me how to write a compiler
Writing a compiler in c doesnt teach you how to write a compiler?
writing the compiler in C also wouldn’t solve my JNI issue
The code I’m compiling does JNI stuff
Idk lock up the jni people and make them fix your issue
Hostage style
Not boring solution
It’s probably my fault that there’s problems anyway
I am the problem
write the compiler in zig
root.toTargetMachine(
new Target(
Architecture.X86_64,
Vendor.APPLE,
OperatingSystem.WINDOWS,
Environment.NEWLIB
),
CPU.GENERIC
);```this seems like a good target config
(according to ChatGPT, setting APPLE as the vendor is good for debugger support)
I'll probably play around with environment a bit more when I actually have a compiler up and going for ralux
for simplicity reasons I'm making my own int to string function for now
it will have one small problem for now: it builds the string backwards 
so if you give it 1234, it'll output 4321
that is, if it works
which I would be shocked if this works first try
it segfaults the ir builder 
ech
GEP really likes to cause me pain
fortunately, adding a little bit to my C test file and telling LLVM to compile it to IR tells me exactly why it's causing me pain in this case
Call parameter type does not match function signature!
[6 x i8]* @Hello
i8* %callPuts = call i32 @puts([6 x i8]* @Hello)
Failed to verify function main
Both operands to a binary operator are not of the same type!
%offset_to_utf = add i32 %get_last_digit, i8 48
Invalid bitcast
%as_int8 = bitcast i32 %offset_to_utf to i8
Invalid bitcast
%as_int64 = bitcast i32 %index1 to i64
Failed to verify function intToString
Call parameter type does not match function signature!
[6 x i8]* @Hello
i8* %callPuts = call i32 @puts([6 x i8]* @Hello)
Both operands to a binary operator are not of the same type!
%offset_to_utf = add i32 %get_last_digit, i8 48
Invalid bitcast
%as_int8 = bitcast i32 %offset_to_utf to i8
Invalid bitcast
%as_int64 = bitcast i32 %index1 to i64
makes sense
i8* %callPuts = call i32 @puts([6 x i8]* @Hello)
wait that's not valid?
... but it works
%callPuts = call i32 @puts(i8* getelementptr inbounds ([6 x i8], [6 x i8]* @Hello, i64 0, i64 0))
well this is what is valid, so 🤷 ig
now to debug why I get empty string from my int to str
reason for my code not working: I used EQ instead of NE
👏
that was the only bug after fixing the stuff that was flat out invalid and prevented it from building
LLVM ERROR: Unsupported library call operation!
ah yes
unsupported library call operation
clearly the correct error message for someone using a 32768 bit integer
it performed the analysis and then told me it couldn't perform analysis
(blue icon is labeled "View Analysis" and shows the same code as the previous requests)
either that or it still generates the analysis and then doesn't run it
claude recently got updated
it's supposed to be better at code now
I can't tell the difference
they didn't version it though, just "new"
also computer use
ok bug located
this happens if you use negatives

that's not a fun one to fix
I know exactly what's happening
rem returns a signed integer
so if I give it a negative number, I get a negative number back
which... results in that
I... think?
yeah
this website just flat out lied to me 👏
result there should be -3
I'mma just use a branch for now I guess
or maybe forever, since I can just setup the ralux compiler to always go agressive mode when optimizing this function and LLVM is incredible at optimizing stuff and should actually get optimal code for this assuming the actual logic is optimal
also I kinda wanna implement as much stuff in ralux as I can to maximize portability
'cuz I want ralux to feel like a high level lang
... and suddenly my code depends on msvc it seems..?
... llvm is inserting stack protection stuff automatically, what
I just always alt tab to my browser and open the dev console and do modulo or whatever in there 
I have a powershell helm thing I should really use it
I'm starting to just go to one compiler lua when I want to run stuff :iea:
slowly
turns out not using branching is really easyjava LLVMValueRef conditionPN = root.compareInt(ECompOp.GE, arg1, zero, "comp_val_pos"); dig = root.select( conditionPN, dig, root.negate(dig) );
that's a nice thing to have added to my toolkit; will really come in handy for null init and mentally reboots ternaries
close enough
why is my - sign a ]? 
is this ascii?
no
-3 gets a -, but I'm not sure if it's the correct -
it is
... I'mma guess this is a locale thing, because chatgpt agrees that that should not be the case
in like every encoding that exists, 45 is -
not -3
now the only thing left for my to string function is to reverse it
oh also I need to fix the case of number==0
because 0 currently yields an empty string but should yield 0 as a string
but I think I'll fix that after I have a compiler, so I don't have to do it in raw LLVM IR
reverse can also come after a compiler ig
I can deal with the backwards strings while debugging stuff 🤷
public static abi int puts([+ AbiType: byte* +] String text);
https://github.com/GiantLuigi4/ralux/commit/8f4233643af62a025f69131ece49ee02895a4797
and thus next commit marks the start of the ralux compiler being a compiler
[+ NumericPrims->T int +]
[+ T->SizeOf->size +]
public static String intToString(T integer) {
char[] buffer = new char[size];
// TODO: implement
return null;
}```ralux compiler hints are gonna be so fun to mess with
average java programmer trying not to have CompilerInvokerFactoryPatternMaker
CompilerInvoker is a test class
It just runs the compiler with a simple test file
I hate the dumb enterprise object factory builder blah blah blah nonsense
based java programmer
java enterprise codebases are a nightmare
Builders are nice
But you don’t need builders for bloody everything
You got like two parameters? Just use a freaking constructor like a sane person
Got 20 parameters, or like 3+ optional parameters? Now THAT’S a topic for a builder
ye
Builder style setters are also just nice to use instead of regular setters
‘Cuz then you can chain .setThing()
But that doesn’t require a dedicated builder class 
I dont like getters and setters personally, unless its used for like some internal thing
Agreed
There are cases where setters on public things are nice
But usually I’d prefer to just access the field directly
ye
getters on public things are good for mod support though
or
ig just getters and setters in general
‘Cuz it creates a convenient place to hijack stuff
BuilderRoot extends ModuleRoot extends ContextRoot
That’s a trick I learned from mojang; BuilderRoot is a large file so I separated it into three files to break the code apart a bit
Probably gonna split it up even further later on
The Level (World) class in minecraft is a tree of like… I think at least 10 interfaces and probably like 3-5 abstract classes
Because it’s just such a large thing that’d be a mess elsewise
// TODO: scope nonsense (and I really mean nonsense, 'cuz it is gonna be some really real nonsense)
Value currentValue;
for a second I just got really scared about ternaries
then realized I have nothing to worry about
I'm also probably gonna implement arrays as a pointer and an integer tbh
antlr->llvm for expressions is gonna not be fun
; ModuleID = 'module'
source_filename = "module"
define i32 @main() {
entry:
%i = alloca i32
store i32 0, i32* %i
}```I can now compile```java
int i = 0;
store i32 10, i32* %i
and various other integer constants
because it would be silly if I couldn't do other int constants
lol
next comes
i += 5;
and then
return i;
public static int main() {
being a native lang, main returns an int
this compiler is not going to be used for mc mods
antlr can compile to java, so java ended up being convenient in the short term
... probably would've been easier to use C# or C++ or like anything that is not java for this compiler though
but at this point I have enough of a system setup that I don't really care to switch 🤷
Might also give vulkan another try with ralux
Not sure
Probably gonna design the wrapper before I hook up vulkan this time if I do, to force myself to create an API I’m happy with instead of making the API around vulkan
I wouldnt recommend fitting an opengl api to vulkan
From what I’ve seen from other game engines/renderers is vulkan focused rhis apply well to other gApis, while other gApi focused rhi’s do not apply well
Ok but also I don’t want creating a framebuffer to require me to through a 5 step process and track like 20 objects or whatever
Whar
Do you not use dynamic rendering
Also in most abstractions you shouldn’t even need to think about framebuffers
My framebuffers were a CPU data structure, ‘cuz yes, I was using dynamic rendering
But I was keeping track of far too many objects throughout my program with my vulkan based renderer
I’m just used to having framebuffers due to working with opengl and minecraft 
Yeah you’re doing something fuckedd then
Wasn’t or was using dynamic rendering
My FrameBuffer class just sorta held the list of things to use for the dynamic rendering pass
Commandbuffer != framebuffer
Two separate concepts
Command buffer is the actual object we submit gpu commands to, framebuffer describes attachements, draw extent and other state
I’m aware
Why do you have an explicit framebuffer object when you already have enough info to setup a framebuffer on the fly 😭
smth smth render passes
A renderpass object should contain the info to setup a framebuffer
https://github.com/GiantLuigi4/renirol/blob/136c4fea44b8f71af3b4a13b153517d4fa394ce1/src/test/java/tfc/test/tests/Main.java#L28
I didn’t like doing this, so I setup my Framebuffer class to do that for me
almost 0 of the functions in this file are actually exposed to the user, it does it for you here as well
And again, used to opengl 
Opengl framebuffer setup is a nightmare for memorization
I tend to like a mixture of high and low level, personally
Abstraction over gl is a nightmare in general
Mojang did it pretty well
define i32 @main() {
entry:
%i = alloca i32
store i32 15, i32* %i
%compute_sum = add i32* %i, i32 5
store i32* %compute_sum, i32* %i
%get_value = load i32, i32* %i
ret i32 %get_value
}```nice
next is expression trees
there's a plugin to represent classes as 3d graphs of methods and variables and params and constructors
what. the heck.
(Graph Buddy)
are these s-expressions?
s-expressions?
polish notation
- 1 2
= 3
the operator followed by the arguments
instead of a LH operator RH
1 + 2
oh
previously it was onlyjava int i = 15; i += 5; return i;
= 3
now it'sjava int i = 15; i += 5 + i; return i;
what's this?
this java file represented as a graph
ah
it's an intellij plugin called Graph Buddy
so the app is intellij :iea:
looks a lot nicer in 2d with small classes
same class with vars and params shown
define i32 @main() {
entry:
%i = alloca i32
store i32 15, i32* %i
%get_value = load i32, i32* %i
%compute_quotient = sdiv i32 5, %get_value
%compute_sum = add i32 %compute_quotient, 3
%compute_diff = sub i32* %i, i32 %compute_sum
store i32* %compute_diff, i32* %i
%get_value1 = load i32, i32* %i
ret i32 %get_value1
}
int i = 15;
i -= 5 / i + 3;
return i;
compiling multiple functions (of course) also works
granted they can't
interact with eachother at all yet
probably gonna make my own IR format at some point
'cuz performing analysis of my own is kinda difficult with LLVM IR
It can be fun
Both operands to a binary operator are not of the same type!
%compute_diff = sub i32* %i, i32 %compute_sum6
Stored value type does not match pointer operand type!
store i32* %compute_diff, i32* %i
i32Both operands to a binary operator are not of the same type!
%compute_sum10 = add i32* %i, i32 %get_value9
Stored value type does not match pointer operand type!
store i32* %compute_sum10, i32* %i
i32Failed to verify function main
Both operands to a binary operator are not of the same type!
%compute_diff = sub i32* %i, i32 %compute_sum6
Stored value type does not match pointer operand type!
store i32* %compute_diff, i32* %i
i32Both operands to a binary operator are not of the same type!
%compute_sum10 = add i32* %i, i32 %get_value9
Stored value type does not match pointer operand type!
store i32* %compute_sum10, i32* %i
this is why you make sure you validate your llvm ir before you try to implement new features
(I forgot a .getValue())
er
yeah
-13492
-13492```java
pkg tfc.test;
public class TestClass {
public static int main() {
int i = 15;
i -= 5 / (i + 3) + i * i * i + (5 + 8);
int 3a = 3 * i;
i += 3a;
return i;
}
}```sweet
next up: the rest of the integer types
or ig coercion
whatever breaks the compiler first
coercion it is!
if (impl.symbol.getText().equals("boolean")) isInt = !(isBool = true);
```java is fun
... what
80 bit floating point number
that's not even a power of 2, what
why
regardless; fp types come next though
public Type coerce(BuilderRoot root, Type type) {
// if (!this.equals(type)) throw new RuntimeException("NYI");
if (intInt(type)) {
if (signed && type.signed) {
int selfSize = root.getIntSize(llvm);
int otherSize = root.getIntSize(type.llvm);
if (selfSize < otherSize) return type;
return this;
} else if (!signed && !type.signed) {
// int selfSize = root.getIntSize(llvm);
// int otherSize = root.getIntSize(type.llvm);
//
// if (selfSize < otherSize) return type;
// return this;
throw new RuntimeException("NYI");
} else throw new RuntimeException("NYI");
} else {
if (isInt || type.isInt) {
if (isFloat() && type.isInt) {
throw new RuntimeException("NYI");
} else if (isInt && type.isFloat()) {
throw new RuntimeException("NYI");
} else {
throw new RuntimeException("NYI");
}
}
throw new RuntimeException("NYI");
}
}```type coercion functions are
quite something 
%14 = call double @pow(double %13, double 4.000000e+00) #5
funfact: LLVM does not optimizepow
%14 = %13 * %13
%15 = %14 * %13
(or at least, I'm pretty sure that'd be faster, gonna wanna profile that at some point)
probably faster for ints, considering C pow function is only applicable for doubles
quadruple fv = 2;
fv += 2;
half i = fv * 10;
fv /= 2;
fv /= 4;
fv *= 100;
i += fv;
int asInt = i;
return asInt;```
quadruples, stretches, and halves
… things I will probably never use
Actually I might end up using halves
Next things:
- return types
- params
- calls
... I just realized
I'm gonna need to make LLVM not always optimize out casts...
'cuz I do sometimes use casts to manipulate data
(i << 24) >> 24 is annoying way to do what (byte) i does
I used nasm like once and suddenly I can figure out bitshifts in my head
well not like once but like
public static stretch main() {
quadruple fv = 2;
fv += 2;
half i = fv * 10;
fv /= 2;
fv /= 4;
fv *= 100;
i += fv;
return i;
}```anyway, return types can now be specified 🎉
public static abi int puts([+ AbiType: byte* +] String text);
public static abi [+ AbiType: void* +] void[] memcpy(
[+ AbiType: void* +] void[] dst,
[+ AbiType: void* +] void[] src,
unsigned long count
);
public static abi [+ AbiType: void* +] void[] realloc(
[+ AbiType: void* +] void[] ptr,
unsigned long new_size
);```abi is gonna be
interesting to implement
to say the least
(void[] will probably only be valid for abi; outside of abi I'm probably gonna enforce generic types)
OH
RIGHT

I should probably parse all method headers before I start parsing methods
yeah that would probably save me a truckload of problems, lol
define i32 @main() {
entry:
}
define i32 @test(i32, i32) {
entry:
%lh = alloca i32
store i32 %0, i32* %lh
%rh = alloca i32
store i32 %1, i32* %rh
%fv = alloca fp128
store fp128 0xL00000000000000004000000000000000, fp128* %fv
%get_value = load fp128, fp128* %fv
%compute_sum = fadd fp128 %get_value, 0xL00000000000000004000000000000000
store fp128 %compute_sum, fp128* %fv
%i = alloca half
%get_value1 = load fp128, fp128* %fv
%compute_prod = fmul fp128 %get_value1, 0xL00000000000000004002400000000000
%cast_fp_to_fp = fptrunc fp128 %compute_prod to half
store half %cast_fp_to_fp, half* %i
%get_value2 = load fp128, fp128* %fv
%compute_quotient = fdiv fp128 %get_value2, 0xL00000000000000004000000000000000
store fp128 %compute_quotient, fp128* %fv
%get_value3 = load fp128, fp128* %fv
%compute_quotient4 = fdiv fp128 %get_value3, 0xL00000000000000004001000000000000
store fp128 %compute_quotient4, fp128* %fv
%get_value5 = load fp128, fp128* %fv
%compute_prod6 = fmul fp128 %get_value5, 0xL00000000000000004005900000000000
store fp128 %compute_prod6, fp128* %fv
%get_value7 = load fp128, fp128* %fv
%get_value8 = load half, half* %i
%cast_fp_to_fp9 = fptrunc fp128 %get_value7 to half
%compute_sum10 = fadd half %get_value8, %cast_fp_to_fp9
store half %compute_sum10, half* %i
}```uh
that ain- oh
define i32 @main() {
entry:
%fv = alloca fp128
store fp128 0xL00000000000000004000000000000000, fp128* %fv
%get_value = load fp128, fp128* %fv
%compute_sum = fadd fp128 %get_value, 0xL00000000000000004000000000000000
store fp128 %compute_sum, fp128* %fv
%i = alloca half
%get_value1 = load fp128, fp128* %fv
%compute_prod = fmul fp128 %get_value1, 0xL00000000000000004002400000000000
%cast_fp_to_fp = fptrunc fp128 %compute_prod to half
store half %cast_fp_to_fp, half* %i
%get_value2 = load fp128, fp128* %fv
%compute_quotient = fdiv fp128 %get_value2, 0xL00000000000000004000000000000000
store fp128 %compute_quotient, fp128* %fv
%get_value3 = load fp128, fp128* %fv
%compute_quotient4 = fdiv fp128 %get_value3, 0xL00000000000000004001000000000000
store fp128 %compute_quotient4, fp128* %fv
%get_value5 = load fp128, fp128* %fv
%compute_prod6 = fmul fp128 %get_value5, 0xL00000000000000004005900000000000
store fp128 %compute_prod6, fp128* %fv
%get_value7 = load fp128, fp128* %fv
%get_value8 = load half, half* %i
%cast_fp_to_fp9 = fptrunc fp128 %get_value7 to half
%compute_sum10 = fadd half %get_value8, %cast_fp_to_fp9
store half %compute_sum10, half* %i
}
define i32 @test(i32, i32) {
entry:
%lh = alloca i32
store i32 %0, i32* %lh
%rh = alloca i32
store i32 %1, i32* %rh
}```🎉
the number of switches I have in this compiler is unholy
I have never written so many switches in a single project
zig's core language repo features a ton of nested switches
it's also probably why zig's switches are so good, because the devs use them a lot
Object o = getObject();
o ?-> { // if o!=null, do block
System.out.println(o.toString());
}```
as someone who likes nullability
nullability related features are something I'm inclined to think about
still don't know what exactly I want to do console IO stuff as
List<Pair<Pair<String, List<Type>>, Pair<FunctionBuilder, Type>>> funcsByParams = new ArrayList<>();
java devs when being lazy

lld-link: error: undefined symbol: __gnu_f2h_ieee
ugh
I'm gonna have to figure out these link errors at some point
this would be a good thing to generate as a 3d graph imo
... maybe I look into having a graph based file browsing system for ralux dev
define void @recursive() {
entry:
br label %tailrecurse
tailrecurse: ; preds = %tailrecurse, %entry
br label %tailrecurse
}```ah yes, llvm optimized my recursive function
define void @recursive() {
entry:
call void @recursive()
ret void
}```for reference, this is the unoptimized version
due to this optimization, it does not work properly; the program does not crash
it also is not perfectly optimized for the logic it was optimized to, could be optimized to define void @recursive() { entry: br label %entry }
solution: link against clang_rt.builtins-x86_64.lib
unfortunately, still need to link against ucrt.lib for puts though
TIL
in javajava byte b = 0; b = -b;is invalid
why?
because -b casts b to an int
what.
the heck.
0
1
10
-10
-1
2147483647
-2147483648
public static String toString(int integer) {
char[] buf = new char[11];
boolean condPN = integer < 0;
if (integer == 0) {
buf[0] = '0';
return new String(buf, 0, 1);
} else {
int index = 0;
while (integer != 0) {
byte rem = (byte) (integer % 10);
if (condPN) rem = (byte) -rem;
integer /= 10;
buf[index] = (char) (rem + '0');
index++;
}
if (condPN)
buf[index] = '-';
else index -= 1;
for (int i = 0; i < (index + 1) / 2; i++) {
char cl = buf[i];
char cr = buf[index - i];
buf[index - i] = cl;
buf[i] = cr;
}
return new String(buf, 0, index + 1);
}
}```welp that's int to string done (java)
not perfectly optimized even for java, but meh
buf[i] <-> buf[index - i];
value trading
[+ NumericPrims->T int +]
[+ T->SizeOf->size +]
public static String intToString(T integer) {
if (integer == 0) {
return "0";
} else {
char[] buf = new char[size];
boolean condPN = integer < 0;
int index = 0;
while (integer != 0) {
T quotient = integer / 10;
byte rem = (byte) (integer - (quotient * 10));
if (condPN) rem = -rem;
integer = quotient;
buf[index] = (char) (rem + '0');
index++;
}
if (condPN)
buf[index] = '-';
else index -= 1;
for (int i = 0; i < (index + 1) / 2; i++) {
buf[i] <-> buf[index - i];
}
buf = realloc(buf, index + 1);
return (String) buf;
}
}```ralux
line 20:8 mismatched input 'return' expecting {PRIMITIVE, 'new', 'if', 'for', 'while', 'do', 'break', 'continue', 'return', 'unsigned', '+', '-', '*', '**', '/', '^', '|', '&', '%', '||', '&&', '<', '>', '<=', '>=', '==', '!=', '.=', '.!=', '.#', '{', '}', ';', '%infer_semicolon%', '%enforce_semicolon%', WORD}
unexpected return
one of the things I was expecting is return
👏
(it's actually expecting specifically else because my parser is bugged)
if (child.getChildCount() > 5) {
if (child.getChild(5) instanceof RuleContext ctx) {
switch (ctx.getRuleIndex()) {
case RaluxParser.RULE_semi_truck -> {
if (child.getChildCount() > 6)
throw new RuntimeException("NYI");
}
default -> throw new RuntimeException("NYI");
}
} else throw new RuntimeException("NYI");
}```
the amount of throw statements in this compiler is also absurd
qh-
ya know what
i don't care
it doesn't matter for this
what does matter
is that this is printing 94 instead of 0
ah right, debug output is backwards
that's 49, not 94
yeah if statements work properly
flawless string reversal logic
outputs are no longer backwards 
yeah I got annoyed with this that I fixed the ir builder which is a temporary solution until I can compile the standard library
it's really nice
if I do ANYTHING the compiler doesn't support, it just throws an erorr
which immediately tells me where that unimplemented thing should be implemented
next:
- the various types of loops
- &&, ||
- ??
is this in a public repo?
absolutely not usable at all yet
when it is usable, I'm probably gonna go for opengl to get a sense of linkage and stuff
then tackle either vulkan or directx12
might go for directx12, since that's built in to the windows sdk
Imagine
Technically everything can be a for loop 
For every unimplemented code path in the compiler, there is a throw statement or three
print(“bad thing happened”)
exit(1)

Basically 
I really wish vr was less annoying to work with
and I don't mean code wise
I mean the actually taking on and off the headset a million times while developing and testing stuff
I still love the name semi truck 
hm I just thought of something really silly and now I need to test it in java
aw it's not valid
for (int i1 = -1; ((i1 == -1) ? (i1 = 0) : i1) < 5; i1++) {
}```but this is valid
for (System.out.print("Honestly quite"); ; System.out.println(" incredible")) {
}```and so is this
for (int a = 0; a < 100; a+=1) {
print(a);
}```anyway, this now works
gonna go implement break and continue nextjava for (int a = 0; a < 100; continue;) { print(a); a += 1; }
^ this is the silly idea I had for java, which ended up not being valid
do I expect anyone to be crazy enough to do this?
definitely freaking not
so am I going to make it explicitly illegal to do it?
no
for (int a = 0; a < 100; if (a == 50) a += 1; else continue) {
print(a);
a += 1;
}```should also be able to do stuff like this I think 
which is really silly
huh
apparently I wrote this a bit smarter than that
ngl I kinda wanna see control flow in a loop header used in an actual codebase though
for (int a = 0; a < 100; a += 1) {
if (a > 50) continue;
print(a);
}```this now works
now I want to support the meme 
actually
this'd be invalid
... I think I'll make header control flow act upon parent loopjava for (int b = 0; b < 100; b += 1) { for (int a = 0; a < 100; if (a == 50) continue; else a += 1;) { print(a); a += 1; } }so continuing loop with var a in header would continue loop with var b here
I have no reference point for how this should work and it's kinda a meme feature anyway ¯_(ツ)_/¯
but ofc, the show must go on, so I must test it
line 20:61 mismatched input 'a' expecting 'if'
line 20:68 mismatched input ')' expecting {PRIMITIVE, 'new', 'if', 'for', 'while', 'do', 'break', 'continue', 'return', 'unsigned', '+', '-', '*', '**', '/', '^', '|', '&', '%', '||', '&&', '<', '>', '<=', '>=', '==', '!=', '.=', '.!=', '.#', '{', '}', ';', '%infer_semicolon%', '%enforce_semicolon%', WORD}
line 27:17 missing WORD at '('
line 27:18 mismatched input '-' expecting {'<', '[', WORD}
line 29:8 extraneous input 'return' expecting {PRIMITIVE, C_TYPE, MODIFIER, 'static', 'unsigned', '<', '[', '}', ';', WORD}
line 29:16 mismatched input ';' expecting {'<', '[', WORD}
line 32:18 extraneous input 'int' expecting {C_TYPE, MODIFIER, 'static'}```o uh what
oh I don't have else implemented, right 
yeah, works as I described
actually there's a bug in the parser relating to else too
tree_exit22: ; preds = %condition_false25
br label %head19
condition_false25: ; preds = %tail21
br label %tree_exit22
condition_true26: ; preds = %tail21
br label %tail
conclusion27: ; preds = %head19
br label %tail
}```there's a lot of just jump branches that I emit
good thing CFGSimplicifcation pass exists 
I'mma go through llvm versions to try to find the newest that has bindings for passes
looks like 13.0.1 is the latest I can use
after that, some of the things I actually need in order for my compiler to even work disappear
🤷 I can look into porting later when I'm not limited by premade bindings
I think it somehow got stuck in a loop
feel like it's cycling between the same five files or something
though that may be it downoading multiple files at once
hard to tell
oooo
13.0.1 supports coroutines
ok so change of plans
- &&, ||
- support more loop variants
- if/else chains
then maybe... switches?
then improve method lookup
then I suppose garbage collector
how do switches actually work behind the scenes?
I've never understood that
I suppose the best way to find out would be to write a switch in C and compile it to llvm ir 🤷
then objects, then strings, arrays, and finally... linking against C/C++ libraries
And whatever else is missing that I don’t immediately care about 
Just found out
Forums posts can be organized in the channel list by unfollowing and refollowing the post
Do ya want me to ping you when it’s a usable lang or something?
Just wanted to look at the code
Never heard of it
.
ralux is the name of the lang I’m working on
Likely gonna try for general purpose
But I’m primarily planning on using it for game dev stuff
Low level, but meant to feel high level
That’s awesome, sure I will try it out

Will your compiler be an exe or a jar?
jar for a while, will eventually convert to exe
Wanna make sure lang is stable enough before I port the compiler to the lang so I don’t shoot myself in the foot 
Because I have shot myself in the foot at least once by doing stuff like that 
https://github.com/GiantLuigi4/ralux/blob/master/src/main/java/tfc/ralux/compiler/parse/RaluxParser.java
especially when this thing exists 
I probably haven't had a java runtime installed in a decade now :P
I have no java runtime installed on my desktop
Only development kits
If I wanna run a jar, I need to do it from command prompt 
Also, intelliJ idea comes with a jdk, and I only know plugin dev for ij, so naturally I’m only making a ralux plugin for ij for now
I don't have intellij
I probably am not your target user, but I will be happy to give it a try, seems cool
oh!
java ships with a command to convert a jar to an exe 
wonder when that was added
I'mma see if I can get that working
this takes a long time to jar task due to including natives for windows, linux, and mac
which I should look into not doing
ok now I should only be including the natives for the architecture and os I'm building it for
and it still takes really long 
probably the largest jar I've ever made
incredible
oh
I think I may need to make my own JIT if I want to make a VM
'cuz 600mb is ridiculous for embedding 
you don't need to go out of your way for me on this project, I am unlikely user of it, I do like seeing what you're up to. I imagine you must have an idea of what problem you wanted to solve though since you are doing all this work
I am in the business of selecting pixel colors to put into frame buffers
I never knew about jpackage before so I wanted to see if it's viable for stuff
... yeah I'm not downloading something for it
trying to figure out LLVM passes is interesting
entry:
%is_it_zero = icmp eq i32 %1, 0
br i1 %is_it_zero, label %zero, label %not_zerocommon.ret: ; preds = %loop_body, %reverse, %zero
%common.ret.op = phi i32 [ 1, %zero ], [ 0, %reverse ], [ %div_by_2, %loop_body ]
ret i32 %common.ret.opzero: ; preds = %entry
store i8 48, i8* %0, align 1
br label %common.retnot_zero: ; preds = %entry
%comp_val_pos = icmp sgt i32 %1, -1
br i1 %comp_val_pos, label %body.us, label %body
not a fan of having 4 2 instruction branches in a single function though
but I don't think I can resolve that one
LLVMPassManagerBuilderRef builderRef = LLVM.LLVMPassManagerBuilderCreate();
LLVM.LLVMPassManagerBuilderSetOptLevel(builderRef, llvm);
LLVMPassManagerRef pass = LLVM.LLVMCreatePassManager();
LLVM.LLVMPassManagerBuilderPopulateModulePassManager(builderRef, pass);```just found out about this 
my breakpoints are bugged, what
that's a new one to me
oh my order of ops is hecked 
just found out this library throws like a million errors before initializing
(java errors are slow btw!)
br <null operand!>, label %condition_true, label %condition_false
what :car:
why did my compiler not explode
I'm concerned
I forgot a throw 👏
store i32 %19, i32* %4, align 4, !dbg !146
%20 = call zeroext i1 @boolFunc(), !dbg !147
br i1 %20, label %21, label %25, !dbg !147
; <label>:21: ; preds = %0
%22 = call zeroext i1 @otherFunc(), !dbg !147
br i1 %22, label %23, label %25, !dbg !147
; <label>:23: ; preds = %21
%24 = call i32 @puts(i8* getelementptr inbounds ([4 x i8], [4 x i8]* @"??_C@_03CFIIMAOO@lol?$AA@", i32 0, i32 0)), !dbg !148
br label %25, !dbg !151```ok so short circuit eval really is just branch
makes sense
LLVM.LLVMPassManagerBuilderPopulateModulePassManager(builderRef, pass);
LLVM.LLVMAddDeadArgEliminationPass(pass);
LLVM.LLVMAddInternalizePass(pass, 1);
LLVM.LLVMAddMergeFunctionsPass(pass);
LLVM.LLVMAddMergeFunctionsPass(pass);
LLVM.LLVMAddFunctionInliningPass(pass);
LLVM.LLVMAddAggressiveDCEPass(pass);
LLVM.LLVMAddGlobalDCEPass(pass);
LLVM.LLVMAddArgumentPromotionPass(pass);
LLVM.LLVMAddAlwaysInlinerPass(pass);
LLVM.LLVMAddPruneEHPass(pass);
LLVM.LLVMPassManagerBuilderPopulateModulePassManager(builderRef, pass);
root.hyperAggressiveOptimizer(false, pass);
LLVM.LLVMAddStripSymbolsPass(pass);
LLVM.LLVMAddLowerExpectIntrinsicPass(pass);
LLVM.LLVMAddLowerConstantIntrinsicsPass(pass);```when your one and only purpose is to optimize the program
Exception in thread "main" java.lang.ClassCastException: class tfc.ralux.compiler.parse.RaluxParser$DOperandContext cannot be cast to class tfc.ralux.compiler.parse.RaluxParser$OperandContext (tfc.ralux.compiler.parse.RaluxParser$DOperandContext and tfc.ralux.compiler.parse.RaluxParser$OperandContext are in unnamed module of loader 'app')
th is a DOperandContext
Lyzantra
ohh
++
well one of the two is faster
not sure which
module 2 looks to be flickering faster actually
... I can't tell 
actually I think module is the faster one
... and module is this, so if so that'd make sense
🤷 it's too early for me to be caring this much about optimization
ever wondered what a codebase looks like as a graph?
The problem I’m trying to solve is
one that not many people care about, since in most cases just use a VM lang or just use a high level lang is an option
and it, honestly is an option for me to, but I want to be free to mess around with bindings without writing this monolithic C or C++ codebase to go along with my java project (kinda, defeating the purpose of java) and I want to be able to Just Use IntelliJ IDEA because that’s what I’m used to
So I’m basically just trying to get this to work for me
if it becomes something people use, then it becomes something people use 🤷
I’d love to see that happen, but I don’t expect it
also I don’t, entirely want to learn native interop with C#, it irrationally scares me for some reason 
also I wanna learn compiler infrastructure stuff, and making a compiler is the best way to do that 
C# is a great language
unfortunately I’m an intellij idealist 
also learned something about java today that now bothers me
protected is package OR subclasses, not just subclasses
Also I’m kinda curious how far LLVM would optimize a software raster that is entirely inlined to be a single function
you can write C++ and C in intellij
all the features of C Lion work in Intellij ultimate I would expect
… well, I don’t have ultimate
you can probably get it as a student
Get free access to all developer tools from JetBrains!
oh I think they’re also doing a thing recently where more of their IDEs are free, but you have to have data collection on if you use it for free
which like
good enough for me tbh
https://www.jetbrains.com/rider/
rider seems to also just be free (for non commercial use), actually
Develop .NET, ASP.NET, .NET Core, Xamarin or Unity applications on Windows, Mac, Linux
I’ll check that out when on my laptop
ok, rider is downloading
long_circuit: ; preds = %entry
br label %tree_exit15
why is it so hard to get llvm to optimize out these branches that literally do nothing other than just jump to another branch
... regardless; next thing is to implement the ability to compile multiple files and import stuff
I don't think I even remember ever having this process occur with IDEA
I mean it must've but like
I have no memory of it
rider installed
rider installed
I will need to register an account 
lld-link: error: undefined symbol: __fixtfsi
I love having no idea what library provides what
according to chat gpt it comes from rt builtins
I'm already linking against rt builtins
wait what
Possible cause: I’m using an older version of LLVM to link my module than I’m using to generate my module
Weird
private T[] ts;
I sure do love when the ide automatically inserts the private qualilfier
wat
so far the weirdest thing to me with C# is this
because this is valid in java, but in C# it has to be this
but apparently this is valid, that's neat
lld-link: error: could not open 'libcmt.lib': no such file or directory
updating lld did not help
it made it worse
maybe I should just make an issue report on llvm
'cuz I can't find anything at all on this and no matter what random files I link against it doesn't help and AI keeps telling me to go depend on MSVC (visual studios compiler, which would mean that people would have to install visual studios to use my language, which seems dumb)
and AI also tells me to use mingw, which like
I'm using llvm because mingw is kinda eh at existing on windows?
so like I don't really want to use it because it's kinda more effort to install than its worth?
and literally nothing I do brings me any closoer to having it work
private T[] ts = Array.Empty<T>();
... why does java not have this
(generic typed arrays are pain to initialize on java)
ok this is awesome
but I just can't stand having stuff abruptly get typed
my complaint with this is exactly the same as my complaint with github copiloit
I end up spending a bunch of time undoing what the ML assistant does
... turns out that's not what's doing it, ech
... I don't know what to call this behavior
well my quickly written list class works 🤷
either that or I guess I just need to make my own runtime lib
maybe that's worth the effort at this point, idk
probably after I have ralux up and running though, so I can write the lib in ralux, since ON-5 doesn't trigger any of these so far, and I don't think ON-4 does either
oh nope, O4 can still cause it :yipee:
to be fair, if someone is building your compiler from scratch, I would also expect them to have msvc
problem: I'm not building the compiler, I'm using the compiler
the compiler's written in java, there's no chance I run into this problem building the compiler
are you trying to do os operations through the c standard library without linking to your c standard library
I believe llvm does that
I believe these are actually intrinsics, not c api stuff
these are things my code doesn't reference; llvm is putting these in itself
I link to both ucrt (from the windows kit) and clang-rt.builtins
LLVM.LLVMAddInternalizePass(pass, 1);
LLVM.LLVMPassManagerBuilderPopulateModulePassManager(builderRef, pass);```this seems to be the minimum pass set for eliminating them
and I've tried linking against like every single lib I could find from both llvm and windows kit
and I don't even know what libcmt is, but whatever it is, I'm gonna pretend I don't have it, because I don't want it to be required to even just use my compiler
why the fuckk are you statically linking to these for a compiler
also libcmt is the c runtime, so prolly important
because the linker throws errors if I don't link my generated code to them
< without clang-rt.builtins
without ucrt >
... then where would I find it that is not msvc
dynamically link them for version support
-llibcmt seems to just work
I have no idea how to dynamic link
uh-huh
oh you're in lld
(I've gone over stuff like that like a million times with chatgpt already)
why would you use chatgpt
using clang does stuff like this
because I've tried the internet and that also hasn't really been giving me answers that are usuable
well why are you using gnu intrinsics when compiling with clang
I'm not using any intrinsics
if anything it should be using uclib intrinsics, because I'm setting my environment as uclib
but it doesn't seem to care about that
also, is there only one obj file that you're linking? if not then you need to include the other ones
I would just *.obj
I only have one obj file
lld-link test.obj /OUT:test.exe \
pcre2-8.lib gc.lib iconv.lib \
libcmt.lib libvcruntime.lib libucrt.lib kernel32.lib dbghelp.lib shell32.lib ole32.lib advapi32.lib \
/ENTRY:wmainCRTStartup /LIBPATH:`crystal env CRYSTAL_LIBRARY_PATH`
"lld-link.exe module.obj -entry:main /libpath:"C:/Program Files (x86)/Windows Kits/10/Lib/10.0.22621.0/ucrt/x64" ucrt.lib /libpath:"C:/Program Files/LLVM/lib/clang/8.0.1/lib/windows" clang_rt.builtins-x86_64.lib
yeah I uh
already have a command that works
problem is it only works if I use optimization level ON-5 or add these two passes because elsewise it fails to link against stuff that my code doesn't reference
whats wrong with the two passes
lld-link module.obj /OUT:module.exe \
libcmt.lib
/ENTRY:wmainCRTStartup /LIBPATH:`path to your libs`
well considering I'm pretty sure llvm only inserts these calls to missing functions for sake of removing undefined behavior
I'm pretty sure those passes introduce undefined behavior
and even if not, it's still not O0, and can introduce behavior that doesn't necessarily line up considering this also requires LLVM level 1
also yes I know how to link against libcmt.lib, problem is I have no idea where it's located
also libpath is necessary
sadly this isn't linux and nothings under one unfied directory
for, specifically ucrt.lib and nothing else
wait no that's because I typed stuff wrong
nope lib path is entirely necessary
you never provided a libpath for libcmt either
yeah because I don't know what said libpath is, so how am I supposed to provide something that I don't know
only thing I have found about libcmt is that it's from msvc
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.41.34120\lib\x64
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.37.32822\lib\x86\libcmt.lib
yeah
msvc
which I don't have a guarantee is on the user's computer
and is also not located where the internet told me it is
again, if someone is installing and using your compiler, since msvc is a required dependency they must install msvc
nor does it solve anything 
I'm not using msvc at all
I'm entirely and exclusively using llvm
sadly on windows its all msvc runtimes
regardless; msvc libcmt doesn't solve anything either, so uh
🤷
skill issue
seems I'm just gonna have to make my own runtime thingy
🤷 heck with msvc
I don't need it 
you do though
builtins - a simple library that provides an implementation of the low-level target-specific hooks required by code generation and other runtime components. For example, when compiling for a 32-bit target, converting a double to a 64-bit unsigned integer is compiling into a runtime call to the "__fixunsdfdi" function. The builtins library provides optimized implementations of this and other low-level routines, either in target-independent C form, or as a heavily-optimized assembly.
... so, according to that, the thing that I'm already linking against should have already solved my issue but it hasn't
my stuff works without it exactly as well as with it
which is to say, it doesn't unless I do a dumb work around for the exact same issue with as I get without
so uh, no I don't think I do 
(you're completely missing my point)
well then what is the point
this ran exactly as intended here, though it's not using libcmt
so like, it sure doesn't seem to be explicitly required, and it also doesn't provide the function that's missing
I can set it up to auto link against msvc if it's present, but for the moment it serves no purpose if it's not gonna fix the issue I'm having when compiling without optimization passes, which is currently the only thing I care about
I mean I guess it's required for lld for 13.0.1, actually
but I'm not currently using that version of lld
and using that version doesn't solve anything either
my mind inserted an n't on this
On windows a lot of the systems libraries are related to msvc, and a lot of people use native systems libraries, just not using them would create a slew of problems
regardless; not relevant to my current problem
I will deal with msvc when I get to that point 🤷
but for now, I'm just sorta working in my own self contained bubble, so it's currently irrelevant unless it actually fixes the problem I'm having
yeah I dont know what the fuckk is happening there, it just looks like you arent linking something somewhere up the chain, and lld isn't picking up on it
seems to have been implemented
I'm pretty sure those are intrinsics operations
which all evidence I've found points to them being included in clang_rt.builtins-x86_64.lib
but I'm already linking to that, so if that's the case, I shouldn't be having this problem in the first place
strange
yeah
I'm also currently unable to use anything higher than llvm 13.0.1, since newer versions remove some things I currently need
but even then, what the heck
some of if not all of these things are generated by even 8.x
is clang_rt an importer library or a static lib
.lib can be both importer libs and static libs
I have no idea how I would check that then
it doesn't seem to have an associated dll and builtins would make me think its a static lib
is this relevant to you at all?
I think you wanted to say that you can ship a lld-link.bat and not cannot. We did consider this, but it would be very complicated bat script or changes to the clang driver in that case, considering how different the link.exe command line interface is from what clang is today. It’s possible, but it’s not a small effort.
doesn't look to be, considering I've already manually added lib/clang/13.0.1/lib/windows to my search paths
adding higher level directories doesn't help either
also still have a question unanswered
whats wrong with the extra passes
I want O0-0 to actually be no passes at all
just the raw compiler output, verbatim, exactly as is
ah
I would just post on the llvm forumns at this point
also singleton datatypes seem like a neat idea```java
public singleton SingletonType {
private static Object someDataThatIsStoredHereButNeededElsewhere;
public SingletonType() {
}
public Object get() {
return someDataThatIsStoredHereButNeededElsewhere;
}
}```
then in some file you do
private static final SingletonType accessor = new SingletonType();```
and if some other code snippet else tries that, well the program crashes
so just a data type that you can only ever initialize once
(this is the most common way I personally use singletons)

?
Sometimes internals need to access internals
and sometimes it’s nice to have those internals be in separate packages
this is an easy way to keep the internals protected while allowing them to be in separate packages
I use singletons so that I can change the values from one and only one location, and said location is not the defining class
I primarily just use them for data protection in ways that access qualifiers aren’t capable of doing
For those cases, having it just be one class file would be
… messy, at best
I also usually only do this with data loaders
I feel like this is a fundamental structure problem but that works
If I need to share values between two instances of a class
- make them the same class
or - just get a pointer to the value
apparently, returning an integer from a void function segfaults the compiler
which, makes sense 
so...
- while
- do while
- else/else if
- fields
- assignability checking
- fix short circuit eval
- objects
- gc
- instance fields&methods
- ralux specific syntax features
I would imagine it would do better if I just kept reusing a single "dirt" variable instead of allocating one per short circuit branch
render the dirt as a dirt texture so we can see some pixels
btw #lang-dev might be interested in your stuff here
@lethal axle tried claude today and
holy heck does claude know what it’s talking about
Based on LLMs from scratch, if asked, claude can actually generate something that looks relatively right for not just a general overview of an LLM architecture
Unlike chatgpt and llama, which struggle to even just do an overview of an llm model
claude is a better model in my experience
It doesn’t generate images though and doesn’t have other features chat-gpt has
Also knows a good bit about apache mxnet it seems, including that it’s no longer mainted
I stopped paying for other models
I have no interest in those features anyway
Claude’s got more features that I care about and less features that I don’t 🤷
a perfect tradeoff imo
I agree
It can still be wildly inaccurate
It tries to agree to a fault
Anthropic calls this sycophantic behavior and they study it
wait I'm dumb
I was looking at the unoptimized module
BlockBuilder builder = root.getBlockBuilding();
LLVMValueRef valueRef = consumer.getDirtRef();
BlockBuilder branchLong = consumer.getDirect().block("long_circuit");
BlockBuilder branchJump = consumer.getDirect().block("jump_circuit");
BlockBuilder branchShort = consumer.getDirect().block("short_circuit");
builder.conditionalJump(left.llvm, branchLong, branchJump);
branchJump.enableBuilding();
root.setValue(valueRef, root.integer(0, 1));
branchJump.jump(branchShort);
branchLong.enableBuilding();
Value right = compileExpr((RaluxParser.ExprContext) context.getChild(2));
root.setValue(valueRef, right.llvm);
root.getBlockBuilding().jump(branchShort);
branchShort.enableBuilding();
val = root.getValue(valueRef, "get_dirt");```well my short circuit eval was also broken anyway, so that's fixed now
O3-5 moment
try((
fis
) -> {
// error prone code
}).with(new FileInputStream("test.txt")).catch((IOException ioe) -> {
ioe.printStackTrace();
});```kinda like this for error handling syntax
System.out.println(new String(proc.getInputStream().readAllBytes().readAllBytes()));
good job intellij
(context: .readAllBytes() returns a byte[], which has no methods, so calling .readAllBytes() again is a compiler error)
(this is a sarcastic good job)
as a human being
I get bored sometimes
lowLevelVirtualMachineParameterValueReferenceWrappedUsingAJavaObjectWhichHoldsALongWhichRepresentsTheMemoryAddressOfTheObject
average java variable name
I think I'm gonna get started on RLXIR (intermediate between ralux and llvmir/other backends)
(I want to be able to have a system where people can just sorta drop a DLL into a folder and add a new compilation target or a new pass set or whatever)
List<RlxCls> classes = new ArrayList<>();
and because ralux is an object oriented lang, yeah I'm gonna make classes a proper thing in rlxir
also would be able to reuse rlxir for other langs :iea:
perhaps it could be useful for lua compilation, donno
will see
first try figuring out gradle subprojects!
@Override
public String toString() {
return switch (typ) {
case 'i' -> "int" + bits;
case 'f' -> "float" + bits;
case 'c' -> "char" + bits;
case 'v' -> "void";
case 'p' -> "pointer";
default -> throw new RuntimeException("qhat");
};
}```I remember when switch statements were the most ugly things in the world with java
ConstInstr<Integer> CONST_2 = new ConstInstr<>(2, RlxTypes.INT);
ConstInstr<Integer> CONST_4 = new ConstInstr<>(4, RlxTypes.INT);
MathInstr sum = function.sum(CONST_2, CONST_4);
VarInstr var = function.makeVar(sum.valueType(), sum);```that's a lot simpler than LLVM IR
ConstInstr<Integer> CONST_2 = new ConstInstr<>(2, RlxTypes.INT);
ConstInstr<Integer> CONST_4 = new ConstInstr<>(4, RlxTypes.INT);
MathInstr sum = function.sum(CONST_2, CONST_4);
VarInstr var = function.makeVar(sum.valueType(), sum);
ValueInstr val = var.get();
MathInstr sum1 = function.sum(val, CONST_4);
var.set(sum1);```
public void compile() {
BlockBuilder block = builder.block("entry");
block.enableBuilding();
for (RlxInstr instr : instrs) {
switch (instr.type()) {
case CONST -> throw new RuntimeException("Consts shouldn't show up in functions");
case MATH -> {
compileMath((MathInstr) instr);
}
case RETURN_VOID -> root.getBlockBuilding().ret();
case RETURN_VALUE -> {
ReturnInstr ret = (ReturnInstr) instr;
ensureData(ret.valueInstr);
root.getBlockBuilding().ret(ret.valueInstr.getCompilerData());
}
}
}
if (!block.isTerminated()) block.ret();
}```nice
already have support for:
- addition
- subtraction
- division
- multiplication
- return
from rlx ir->llvm ir compilation
next is vars, then fp and type coercions
gonna also have to rewrite the whole ast -> ir compilation process to use rlx ir instead of llvm ir directly, but that should be... a good amount simplier than compiling to llvm ir directly
ight, vars and rets are in
I see a lot of beginner compiler developers do this, I dont see a point in the slightest
why need intermediates for intermediates
I was sorta left unable to really properly do nearly as much analysis as I wanted with LLVM
my intermediate is just sorta a data structure with no file format (currently)
though I also want to be able to export libraries as a file that is not a machine binary but also not just the source code
🤷 I can do without the intermediate for the intermediate, but it just kinda simplifies stuff for me
I mean I probably could do the analysis with llvm but like
eh, it's just easier to have the extra step, lol
see this is a good usecase, ocaml does this, a lot of the times I get the explanation so people can implement other backends, but 100/100 times nobody needs to implement a new backend, and if they do they're certainly experienced enough to either write one for llvm, or fork the compiler and add it
I kinda wanna do different backends at some point but like
eh I probably won't
but I am decently likely to do multiple frontends (largely due to build systems)
I wanna use a variant of LUA for my build system 🤷
trust me, llvm has more than enough coverage
the jvm with automated JNI generation?

idk, its a fucking insanely huge project
zig has like 2 IRs
maybe it's just one
there's AIR and ZIR so I guess that's two
; ModuleID = 'module'
source_filename = "module"
define i32 @"TestClass#testFunction"() {
entry:
%var = alloca i32, align 4
%var1 = alloca i32, align 4
store i32 8, i32* %var, align 4
%get_var = load i32, i32* %var, align 4
%si_sum = add i32 %get_var, 3
store i32 %si_sum, i32* %var, align 4
store i32 6, i32* %var1, align 4
%get_var2 = load i32, i32* %var, align 4
%si_sum3 = add i32 8, %get_var2
store i32 %si_sum3, i32* %var1, align 4
%get_var4 = load i32, i32* %var1, align 4
%get_var5 = load i32, i32* %var, align 4
%si_cmp = icmp sgt i32 %get_var4, %get_var5
br i1 %si_cmp, label %test0, label %test1
test0: ; preds = %entry
%get_var6 = load i32, i32* %var1, align 4
ret i32 %get_var6
test1: ; preds = %entry
%get_var7 = load i32, i32* %var, align 4
ret i32 %get_var7
}```yipee!
ok but why
the actual implementing a backend is not much of a challenge now compared to before 🤷
the front end will be a bit more annoying but rlxir's methods automatically deal with a lot of the annoying stuff (type coercion, auto casts, probably will set it up to handle a decent amount of object structure for me, etc) 🤷
Zig is a case in how not to design a language imo 
I'm gearing rlxir to this whole object orientation centered design that languages like java and C# uses (where basically everything is an object) but in a way that it's easier to translate to LLVM than just the source code alone 🤷
What is wrong with zig?
from a quick glance at a google image of zig code
zig looks to be a blend of a good amount of my favorite parts of a few languages I don't like
as well as some stuff that I would definitely have to learn to understand 
also what is this?
jvm bytecode, where the type comes after the arguments?
Idk I don’t have any problems building anything I want to with zig 
oh right
why is there the _ though
does that tell zig to infer the size? or?
@lethal axle?
I dislike it a lot, and the proponents of it
Ok I guess it’s not for everyone, it’s working for me though idk 
Thats totally fine!
bjorn?
Yes
Sorry I was afk
It’s pretty convenient
It’s a comptime syntax that determines the size of an array by the number of values in the literal
alternatively; []u32{0};
That’s the slice syntax
[] is the zig version of **
Well sorta
It’s a pointer to a collection
You can get a slice from an array
this is invalid syntax
you're not supposed to make arguments about things you don't understand. zig is a great example of how you would write a compiler that needs to combine comptime and runtime code
ZIR and AIR serve different purposes. ZIR is untyped because a fully typed zig program requires comptime evaluation and AIR is a per-function IR used by codegen
I am aware
I am proposing to get rid of the _ and have the lack of anything in the brackets be what tells the compiler to infer the size
mhm iirc there's a proposal for that
although im not in favor of it as that might cause confusion between []u8 (the slice type) and []u8 (the array literal)
ohh
okay what the heck
there's like 2 elements that are responsive and the rest of the UI is frozen 
how does this even occur 
type coercion time 🤷
How do you know I dont know anything about language design :) I would emplore you to check my github, theres also just much easier and intuitive ways than what zig does, for example the jai metaprogramming system, the odin array programming system, and lisp’s metaprogramming system
so now
make arguments about things you dont understand
You did that without any research into one link on my profile, I would say you should also consider this about yourself :^)
Exception in thread "main" java.lang.RuntimeException: float32 cannot be set as a int32. Are you missing a cast?
at tfc.rlxir.instr.value.vars.VarInstr.set(VarInstr.java:23)
at ir_to_ir.Test.main(Test.java:35)
I-
:wha:
the math instruction should be the one crashing the compiler here 
if anything
I stand corrected
ConstInstr<Integer> CONST_5 = new ConstInstr<>(5, RlxTypes.INT);
ConstInstr<Integer> CONST_3 = new ConstInstr<>(3, RlxTypes.INT);
ConstInstr<Float> CONST_6 = new ConstInstr<>(6.0f, RlxTypes.FLOAT);
MathInstr sum = function.sum(CONST_5, CONST_3);
VarInstr var = function.makeVar(sum);
var.set(function.sum(var.get(), CONST_3));
VarInstr var1 = function.makeVar(CONST_6);
var1.set(function.autoCast(
function.sum(sum, var1.get()),
var1.type
));
CompareInstr condition = function.compare(CompareOp.GT, var1.get(), var.get());
RlxBlock blockA = function.makeBlock("test0");
RlxBlock blockB = function.makeBlock("test1");
function.jumpIf(condition, blockA, blockB);
function.ret(var);
function.buildBlock(blockA);
function.ret(var1.get());```
%cast_i_fp_float16_to_float32 = sitofp half %get_var2 to float
incredible
something broke there
yeah that should not be picked up on as an INT_FLOAT cast
cause: I was assuming the left hand coercion cast would always be the same as the right hand coercion cast
which is almost if not actually exclusively false 
I think exclusively false for how my logic was
I'm not gonna bother making my IR readable to a human when dumped to a file
I only need it to be readable to the compiler 🤷
I can even just do a binary data representation and not bother beyond that truthfully, but I like being able to see it as a debug string
it's the code api for working with the ir that needs to be comprehensible
TestClass {
func 3s int32 main() {
entry: # 19 instructions
# TODO: list instr args (as indices)
cd int32 math
define_var # var
d set_var # var
d int32 get_var # var
d int32 math
d set_var # var
define_var # var1
d set_var # var1
d float16 get_var # var1
cd float32 cast
d float32 cast
d float32 math
d float16 cast
d set_var # var1
d float16 get_var # var1
d int32 get_var # var
d int32 cast
d int1 comparison
d cond_jump
test0: # 3 instructions
# TODO: list instr args (as indices)
d float16 get_var # var1
d int32 cast
d return_value
test1: # 2 instructions
# TODO: list instr args (as indices)
d int32 get_var # var
d return_value
}
}
like I'mma just refer to things with the instruction index for instr args, 'cuz while that's really annoying for a human to read, it's really easy to parse that way
(3s stands for package-protected, static)
i meant specially zig, not language design. also sorry for my harsh language 
You're all good, dont worry about it
on a side note like you said, I should probably write a lot more zig before forming opinions, but from the little I have written, it leaves a sour taste in my mouth. It may just need to warm up on me like lisp
my main gripe is the typing system it just feels like things are in the wrong order
const* makes it feel like the const is what we're taking a pointer of, which doesn't make sense
lemme get the whole rant I had
*const [N]<TYPE>
oh
god
pointer to constant N sized type array
?
At the end of the day, just like every other language it's all about the creator's taste. There are people who like it and people who don't.
interestingly, it lines up with the JVM where applicable
(of note: I specified JVM and not any language for a reason)
apparently I can't use LLVM to run functions that take 64 bit integers as parameters
