It is possible. Dynamic code generation is even a major topic in some areas, such as software rendering and graphics. You often use all kinds of script languages ββin the dynamic compilation of bytecode into machine code (.NET, Java, as far as I know, Perl. Recently JavaScript joined it).
You will also find that it is used in applications with very great math. It matters if, for example, you remove all multiplications with zero from the matrix multiplication, if you plan to do such a multiplication several thousand times.
I highly recommend you read the SSA code submission. This is a representation in which each primitive turns into the so-called three-dimensional form, and each variable is assigned only once (hence the same form of static single assignment).
You can run high-order optimization on such code, and it directly translates this code into executable code. You will not write this code to generate code on the weekend, though ...
To understand what SSA looks like, you can try the LLVM compiler. On their website, they have a small "Try" widget that you can play with. You paste the C code into the window and you get something that is close to the SSA form.
A small example of what it looks like:
Let's take this integer square-root algorithm in C. (arbitrary example, I just took something simple but non-trivial):
unsigned int isqrt32 (unsigned int value) { unsigned int g = 0; unsigned int bshift = 15; unsigned int b = 1<<bshift; do { unsigned int temp = (g+g+b)<<bshift; if (value >= temp) { g += b; value -= temp; } b>>=1; } while (bshift--); return g; }
LLVM turns it into:
define i32 @isqrt32(i32 %value) nounwind { entry: br label %bb bb: ; preds = %bb, %entry %indvar = phi i32 [ 0, %entry ], [ %indvar.next, %bb ] %b.0 = phi i32 [ 32768, %entry ], [ %tmp23, %bb ] %g.1 = phi i32 [ 0, %entry ], [ %g.0, %bb ] %value_addr.1 = phi i32 [ %value, %entry ], [ %value_addr.0, %bb ] %bshift.0 = sub i32 15, %indvar %tmp5 = shl i32 %g.1, 1 %tmp7 = add i32 %tmp5, %b.0 %tmp9 = shl i32 %tmp7, %bshift.0 %tmp12 = icmp ult i32 %value_addr.1, %tmp9 %tmp17 = select i1 %tmp12, i32 0, i32 %b.0 %g.0 = add i32 %tmp17, %g.1 %tmp20 = select i1 %tmp12, i32 0, i32 %tmp9 %value_addr.0 = sub i32 %value_addr.1, %tmp20 %tmp23 = lshr i32 %b.0, 1 %indvar.next = add i32 %indvar, 1 %exitcond = icmp eq i32 %indvar.next, 16 br i1 %exitcond, label %bb30, label %bb bb30: ; preds = %bb ret i32 %g.0 }
I know that at first it looks awful. This is not even a pure SSA form. The more you read on this presentation, the more it will make sense. And you will also find out why this concept is so widely used today.
Encapsulating all the necessary information in a data structure is easy. In the end, you need to decide if you want to use enumerations or strings for the opcode code ect name.
Btw - I know that I did not give you a data structure, but a more formal, but practical language and advice on where to look further.
This is a very interesting and interesting area of ββresearch.
Edit: And before I forget this: don't miss the built-in functions of .NET and Java. These words allow you to compile from bytecode or source code from a program and execute the result.
Cheers, Nils
Regarding your editing: how to execute binary with code:
The hint in your binary is OS and platform dependent. In short, you have an insider command cache, you may need to back up the data cache, and you may need to include execution rights in the memory area into which you entered the code.
In win32, this is relatively simple since clearing the command cache seems sufficient if you put your code in a heap.
You can use this stub to start:
typedef void (* voidfunc) (void); void * generate_code (void) {