How to generating LLVM bitcode without the llvm generator tools? - code-generation

I've read through the llvm Kaleidoscope tutorial, but it's about how to use their tools. I'm looking for a way to write my own code that allow me to take an abstract syntax tree and generate the llvm IR.
Unfortunately, I'm a little lost on how to go about doing that. My current idea was to have each node of my AST do a fill in the blank style string generation. However this seems inelegant, and there is probably a better way to do this.
I read this question which is simalar to mine, but from my understanding of the llvm IR, which could be completely off, is that it behaves similar to a higher level language than traditional assembly languages, with it having functions, and variables(infinite registers). So I think different techniques may apply.

Not inelegant at all. Generally speaking: at this point most compilers are likely going to generate some form of IR or VM instruction set which likely gets optimized based on well documented approaches. At the end, the compiler translates that result/outcome to the target machine code.
Think of LLVM-IR as that internal IR that you are going to generate and let the toolchain take care of optimizing and creating machine code.

Related

Does Swift compile to native code?

Simple question really, however there doesn't seem to be a straight answer in the current developer documentation.
Does Swift compile to machine language (i.e. assembly), or does it compile to some intermediary form that then runs on a virtual machine?
(I suspect it does, but being unfamiliar with development in Apple's world it is not clear to me like it may be to someone who is.)
Yes, it compiles to machine language by way of LLVM Bitcode and, as #connor said, runs on top of the Objective-C runtime.
Swift not only compiles to native machine code but it has also been designed specifically for it. Unlike e.g. Java which has been designed specifically as a JITed language. By that I mean Swift achieves best performance with ahead of time compilation while Java benefits most from JITing.
There are many reasons for these design choices but among them is that Swift has a much bigger scope than managed languages like Java. It is supposed to work on both desktop computers and phones with more restricted hardware. You can use Swift as a systems programming language unlike say C#, Java or Python because it has little runtime requirements and allow fairly detailed control of memory. So in theory one should be able to build an OS kernel with Swift which would be difficult with say Java.
Swift, just like objective-c compiles to native code using llvm
A good explanation can be found in Apple's top secret Swift language grew from work to sustain Objective C, which it now aims to replace
From that article, talking about Swift
The compiler is optimized for performance, and the language is
optimized for development, without compromising on either.
Swift, like Objective-C, is compiled to machine code that runs on the Objective-C runtime.

Is there any real advantage from Bytecode JIT execution over native code beside portability? (General and OS-Design)

Is there any real advantage from Bytecode JIT execution over native code beside possible implementation of platform independency?
Apparently languages that use "virtual machines" over Bytecode JIT execution are attributed several advantages. But in what extend would this really affect a discussion concerning advantages/disadvantages of native code and JIT execution?
Here's a list of attributes that I identify, the question is in what extend does this also apply to native code - if the compiler supports it...
Security
VM runtime environments can observe the running application for e.g. buffer overflows.
So first question is if this is done by the "runtime environment", means e.g. by the class library or during JIT execution?
Memory bounds-checking exist also for native code compilers. Any other/general restrictions here?
Optimization
Classical optimization should be possible in native code compilers, too. See LLVM which in fact uses the generated bitcode to run optimization on, before compiling to native code.
Maybe there would be something like a dynamic optimization in JIT by e.g. identifying things to optimize related to the execution context. Could maybe be possible for a native compiler, too, to generate some code to optimize the execution during runtime. But dont't know if something like this is implemented.
Popular VM implementations do this - the question is if this really excuses a real advantages over native code.
Threading
I don't cound this while threading also in a VM is dependent on the native Thread implementation of the OS.
If we identify that there is no real advantage over native code and that there is always a runtime drawback in JIT... than this leads to the next question:
Does an operating system design based on JIT execution (e.g. Singularity, Cosmos, ...) make sense?
I could maybe identify one advantages: An OS with this design needs no MMU. Means there is no process seperation that makes use of the MMU, but a seperation between objects/components in software. But is it worth it?
Best regards ;-)
Theoretically, they could take advantage of the platform/CPU they run on, to compile faster code.
In practice, I personally haven't come across any case in which that actually happens.
But there's also other issues. Higher-level languages that compile into bytecode also happen to have garbage collection, which is very useful in some domains. It's not because of the JIT compiler per se, but having a JITter makes it a lot easier practically because often the language is easier for a JITter to analyze and figure out e.g. where pointers go on the stack, etc.

Is there a way to use assembly hand-coded shaders instead of using GLSL on iPhone?

I would like to use hand-coded assembly language vertex and fragment shaders in order to program very optimized shaders on iPhone with OpenGL ES 2.0.
I googled around but I can't find an example or even if it is allowed by apple sdk.
On the iPhone, there is no way to hand tune shaders. It's worth noting that on the iPhone in particular, there are no optimizations that you can do that a compiler can't. That said, the GLSL compiler will probably beat or match your hand-tuned assembly.
On the PC, however, I personally do not have faith in the driver to know that a looping shader should use fewer registers and more instructions in order to achieve greater throughput through higher occupancy. Drivers simply don't have enough context to make the right choice all of the time. Data-specific compile-time optimizations are a great example of this problem.
As someone who has actually looked at the GLSL compiler's assembly output and tried to game the compiler's register allocation strategy, I can tell you that not having assembly access absolutely does hurt performance (on the PC, there are some publicly available tools from NVidia and AMD that allow you to do this). The trade-off to using assembly is that every shader needs to be hand tuned for every supported part in order to achieve the maximum possible performance. While this is a bit extreme, if I want to invest my own time into fine tuning a rendering back-end for each video card my products support, then I should be able to do so. A more practical example would be hand-tuning for low-end video cards, but letting the GLSL compiler do it's job on more high-end video cards.
Further, offline compilers provide a safety mechanism. Many video games today rely on drivers to emulate a lot of the functionality available in modern graphics APIs. As a game developer who works in the game-as-a-service space on the PC, I can tell you that it's extremely upsetting to get a call in the middle of the night because of a minor GLSL bug in a newly released graphics driver. Driver bugs severely impact the overall player experience. Most players simply think that your game is broken, and you can actually lose players as a result (and we probably have). Being able to compile once for each supported video card and hand-tune after the fact would be a huge win in this regard. It simply means that the driver would have to do less work. Code is evil, so the less code that executes is better =).
As a side note, I made the following demo using the 'compile'-'view assembly'-'modify'-'repeat' approach: http://www.youtube.com/watch?v=km0DpZUgvbg . I can tell you with 100% certainty that I could further improve the performance of this ray-tracer with assembly language, and AFAIK, it's the fastest voxel ray-tracer whose existance has been published (that was the case as of Mar 2012, but is likely no longer true). Unsurprisingly, each time a new driver would come out, I would see this demo's performance go from 125-130 fps down to 30 fps - all because the driver didn't know how to optimize my shader correctly. That means I'd have to repeat my optimization process each time a new driver came out, which caused me to simply mothball the project (ACK!). Even though my voxel raytracer can support a large variety of hardware in a performant manner, drivers are currently making it impossible to support this technology in a full product. I simply do not have the weight to put this technology in action because it would require driver vendors to know the ways in which they need to optimize my shader. How many other technologies would be possible if we simply had direct assembly shader access? This implies that lacking assembly access is actually a serious cost. For anyone else in this position, I recommend the following: Use NVidia's assembly language when possible and fallback to GLSL when it's not. If we show the advantage of assembly over GLSL, then hopefully we'll get first-class assembly support from all vendors =).
And finally, not to pick on another author, but I want to point out that the argument made by 'Nicol Bolas' is almost entirely fallacious (sorry Nicol, I have nothing against you, but I wanted to point out some popular arguments that simply don't hold up to an ethics test). Please note that a fallacious argument does not mean that a particular conclusion is incorrect -- just that the argument posited is simply fallacious.
"Why? You don't trust the compiler to do it's job? Do you really think that you know enough about the GPU in question to be able to consistently beat the compiler?"
This is not an argument. This is simply a question that a lot of people can't think of a real answer to. Therefor, they come to the conclusion that they should just trust the compiler. This prevents people from further investigating the ramifications of trusting the compiler, and prevents logical discourse of the actual pros and cons from taking place. Furthermore, the use of the word "really" in your second question implies that someone answering yes must be deluded. This also hints at what you think about yourself, Nicol -- it implies that you value your opinion above all others, and anyone who doesn't think like you must have something wrong with them (not that they are wrong, but that they have something wrong with them - big difference). That said, you might want to take some time to think about your thought process, your feelings, and your emotional state. Taking this approach will seriously limit your ability to learn, as you won't be challenging your own ideas with enough rigor. Please stop using this argument. It's not healthy or ethical.
"Ultimately, you're just going to have to trust the compiler made by the people who built your GPU. Nobody else has a problem with that these days."
I have a problem with it. Also, even if no one did have a problem with it, that still wouldn't matter. The fact is that there might still be some benefit to allowing assembly shaders. That said, a consensus does not mean correctness. Further, this argument is especially unethical because there is an implied "Nobody else has a problem with that these days so if you have a problem with it, you must be weird or out of date in your thinking". People have a natural desire to fit in, and using this argument is a way of dividing people on this issue and persecuting people that don't think like you. That said, this argument is especially insidious because of it's implications. Please don't use this argument.
Nicol, both of your fallacies imply that you are right and normal, and anyone who doesn't agree with you is wrong and has something wrong with them. These are extremely unhealthy viewpoints, and you should examine them rigorously for your own mental health and career.
For future reference: http://en.wikipedia.org/wiki/List_of_fallacies#Formal_fallacies
Thanks!
I would like to use hand-coded assembly language vertex and fragment shaders in order to program very optimized shaders on iphone with opengl es 2.0.
Why? You don't trust the compiler to do it's job? Do you really think that you know enough about the GPU in question to be able to consistently beat the compiler?
Anyway, you can't. Nor could you do it in desktop OpenGL. ARB assembly shaders aren't that much closer to the hardware than GLSL; they both go through compilation and optimization by an internal compiler.
Ultimately, you're just going to have to trust the compiler made by the people who built your GPU. Nobody else has a problem with that these days.
I understand you point very well : you want to see the generated assembly source code, and maybe modify it.
In fact, GLSL compilers are not optimized in comparison with HLSL ones. To convince yourself, just compare the generated assembly in ShaderAnalyzer for the same shader in GLSL and HLSL ; you will immediately see that they don't give the same optimization at all.
Even for trivial optimizations, like factorizing if() conditions, most of GLSL compilers don't do the job.
I really would like to see the generated ASM by Apple's compiler (especially for iOS platforms). If you know a way to get the assembly, I'm very interested in the process.

Why isn't there a good scheme/lisp on llvm?

There is Gambit Scheme, MIT Scheme, PLT Scheme, Chicken Scheme, Bigloo, Larceny, ...; then there are all the lisps.
Yet, there's not (to my knowledge) a single popular scheme/lisp on LLVM, even though LLVM provides lots of nice things like:
easier to generate code than x86
easy to make C FFI calls
...
So why is it that there isn't a good scheme/lisp on LLVM?
LLVM provides a lot, but it's still only a small part of the runtime a functional language needs. And C FFI calls are uncomplicated because LLVM leaves memory management to be handled by someone else. Interacting the Garbage Collector is what makes FFI calls difficult in languages such as Scheme.
You might be interested in HLVM, but it's still more than experimental at this point.
For CL: Clasp is a Common Lisp implementation on LLVM, and mocl implements a subset of Common Lisp on LLVM.
For Scheme: there's a self-hosting Scheme->LLVM demo and a prototype LLVM backend for Bigloo Scheme.
For Clojure: there's Rhine, which is a Clojure-inspired lisp.
There's a very small and apparently unoptimised Scheme compiler here:
http://www.ida.liu.se/~tobnu/scheme2llvm/
Taking your question literally,
Writing compilers is hard.
A poor implementation like the one linked above can block new implementations. People going to the LLVM page see that there's a Scheme already, and don't bother writing one.
There's a limited number of people who write and use Scheme (I'm one, not a hater, btw).
There are lots of existing Scheme intepreters and compilers and there's not a screaming need to have a new one.
There's not an immediate, clear benefit to writing a new interpreter using LLVM. Would it be faster, easier, more flexible, better in some way than the other dozens of Scheme implementations?
The LLVM project went with another language (C) to demo their technology, and haven't seen a need to implement a lot of others.
I think that it could be a lot of fun for someone to build an LLVM-based Scheme compiler. The Scheme compilers in SICP and PAIP are both good examples.
Maybe I'm completely misunderstanding the question or context, but I believe that you could use ECL, which is a Common Lisp that compiles down to C, and use the Clang compiler to target LLVM (instead of GCC).
I'm not sure what (if any) benefit this would give you, but it would give you a Lisp running on LLVM =].
One thing to keep in mind is that many of these implementations have C FFIs and native-code compilers that significantly predate LLVM.
CL-LLVM provides Common Lisp bindings for LLVM. It takes the FFI approach, rather than attempting to output LLVM assembly or bitcode directly.
This library is available via Quicklisp.
mocl is a compiler for a relatively static subset of Common Lisp. It compiles via LLVM/Clang.
there's not (to my knowledge) a single
popular scheme/lisp on LLVM
Currently, llvm-gcc is the nearest thing to a popular implementation of any language on LLVM. In particular, there are no mature LLVM-based language implementations with garbage collection yet. I am sure LLVM will be used as the foundation for lots of exciting next-generation language implementations but that will take a lot of time and effort and it is early days for LLVM in this context.
My own HLVM project is one of the only LLVM-based implementations with garbage collection and its GC is multicore-capable but loosely bound: I used a shadow stack for an "uncooperative environment" rather than hacking the C++ code in LLVM to integrate real stack walking.
There is a Scheme2LLVM, apparently based on SICP:
The code is quite similar to the code in the book SICP (Structure and Interpretation of Computer Programs), chapter five, with the difference that it implements the extra functionality that SICP assumes that the explicit control evaluator (virtual machine) already have. Much functionality of the compiler is implemented in a subset of scheme, llvm-defines, which are compiled to llvm functions.
I don't know if it's "good".
GHC is experimenting with a scheme backend and getting really exciting preliminary results over their native code compiler. Granted, that's haskell. But they've recently pushed new changes into LLVM making tail calls easier IIRC. This could be good for some scheme implementation.

When generating code, what language should you generate?

I've worked on a number of products that make use of code generation. It seems to be the only way to achieve both a high degree of user-customizability and high execution speed.
The downside is that we are requiring users to install a compiler (primarily on MS Windows).
This has been an on-going headache, because vendors like MS keep obsoleting compilers, and some users tend to have more than one compiler installed.
We're considering using GNU C, and possibly C++, but even there, there are continual version issues.
I've considered possibly generating assembly language, in an effort to get off the compiler-version-treadmill, but assembly languages are all machine-specific.
Ideally there would be some way to produce generated code that would be flexible, run fast, and not expose us to the whims of third-party providers.
Maybe I'm overlooking something simple, like Java. Any ideas would be appreciated. Thanks.
If you're considering C and even assembler, take a look at LLVM first: http://llvm.org
I might be missing some context here, but could you just pin yourself to a specific version? E.g., .NET 2.0 can be installed side by side with .NET 1.1 and .NET 3.5, as well as other versions that will come out in the future. So as long as your code makes use of a specific version of a compiler, what's the problem?
I've considered possibly generating assembly language, in an effort to get off the compiler-version-treadmill, but assembly languages are all machine-specific.
That would be called a compiler :)
Why don't you stick to C90?
I haven't heard much of severe violations of standards from gcc's side, if you don't use extensions.
And you can always distribute a certain version of gcc along with your product, say, 4.3.2, giving an option to users to use their own compiler at their own risk.
As long as all code is generated by you (i. e. you don't embed your instructions into other's code), there shouldn't be any problems in testing against this version and using it to compile your libraries.
If you want to generate assembly language code, you may take a look at asmjit.
One option would be to use a language/environment that provides access to the compiler in code; For example, here is a C# example.
Why not ship a GNU C compiler with your code generator? That way you have no version issues, and the client can constantly generate code that is usable.
It sounds like you're looking for LLVM.
Start here: The Code Generation conference
In the spirit of "might not be to late to add my 2 cents" as in #Alvin's answer's case, here is something I'd think about: if your application is meant to last for some years, it is going to face several changes in how applications and systems work.
For instance, let's say you were thinking about this 10 years ago. I was watching Dexter back then, but I guess you actually have memories of how things were at that time. From what I can tell, multithreading was not much of an issue to developers of 2000, and now it is. So Moore's law broke for them. Before that people didn't even care about what will happen in "Y2K".
Speaking of Moore's law, processors are indeed getting quite fast, so maybe certain optimizations won't be even that necessary. And possibly the array of optimizations will be much bigger, some processors are getting optimizations for several server-centric stuff (XML, cryptography, compression and regex! I am surprised such things can get done on a chip) and also spend less energy (which is probably very important for warfare hardware...).
My point being that focusing on what exist today as a platform for tomorrow is not a good idea. Make it work today, and surely it will work tomorrow (backward-compatibility is especially valued by Microsoft, Apple is not bad it seems and Linux is very liberal about making it work as you want).
There is, yes, one thing that you can do. Attach your technology to something that just won't (likely) die, such as Javascript. I'm serious, Javascript VMs are getting terribly efficient nowdays and are just going to get better, plus everyone loves it so it's not going to dissappear suddenly. If needing more efficiency/features, maybe target the CRL or JVM?
Also I believe multithreading will become more and more of an issue. I have a gut feeling the number of processor cores will have a Moore's law of their own. And architectures are more than likely to change, from the looks of the cloud buzz.
PS: In any case, I belive C optimizations of the past are still quite valid under modern compilers!
I would stick to that language that you use for generating that language. You can generate and compile Java code in Java, Python code in Python, C# in C#, and even Lisp in Lisp, etc.
But it is not clear whether such languages are sufficiently fast for you. For top speed I would choose to generate C++ and use GCC for compilation.
Why not use something like SpiderMonkey or Rhino (JavaScript support in Java or C++). You can export your objects to JavaScript namespaces, and your users don't have to compile anything.
Embed an interpreter for a language like Lua/Scheme into your program, and generate code in that language.