If something can be generated, then that thing is data, not code.
Inasmuch as you stipulate later on that code is data, your proposition reduces to "If something can be generated, then that thing is not code." Would you say, then, that assembly code generated by a C compiler is not code? What if it happens to coincide exactly with assembly code that I write by hand? You're welcome to go there if you wish, but I won't be coming with you.
Let's start instead with a definition of "code". Without getting too technical, a pretty good definition for the purposes of this discussion would be "machine-actionable instructions for performing a computation."
Given that, isn't this whole idea of source code generation a misunderstanding?
Well yes, your starting proposition is that code cannot be generated, but I reject that proposition. If you accept my definition of "code" then there should be no conceptual problem with code generation in general.
That is, if there is a code generator for something, then why not make that something a proper function which can receive the required parameters and do the right action that the "would generated" code would have done?
Well that's an entirely different question, about the reason for employing code generation, rather than about its nature. You are proposing the alternative that instead of writing or using a code generator, one writes a function that computes the result directly. But in what language? Gone are the days when anyone wrote directly in machine code, and if you write your code in any other language then you depend on a code generator in the form of a compiler and / or assembler to produce a program that actually runs.
Why, then, do you prefer to write in Java or C or Lisp or whatever? Even assembler? I assert that it's at least in part because those languages provide abstractions for data and operations that make it easier to express the details of the computation you want to perform.
The same is true of most higher-level code generators, too. The prototypical cases are probably scanner and parser generators such as
yacc. Yes, you could write a scanner and a parser directly in C or in some other programming language of your choice (even raw machine code), and sometimes one does. But for a problem of any significant complexity, using a higher-level, special-purpose language such as lex's or yacc's makes the hand-written code easier to write, read, and maintain. Usually much smaller, too.
You should also consider what exactly you mean by "code generator". I would consider C preprocessing and the instantiation of C++ templates to be exercises in code generation; do you object to these? If not, then I think you'll need to perform some mental gymnastics to rationalize accepting those but rejecting other flavors of code generation.
If it is being done for performance reasons, then that sounds like a shortcoming of the compiler.
Why? You are basically positing that one should have a universal program to which the user feeds data, some classified as "instructions" and others as "input", and which proceeds to perform the computation and emit more data that we call "output". (From a certain point of view, one might call such a universal program an "operating system".) But why do you suppose that a compiler should be as effective at optimizing such a general-purpose program as it is at optimizing a more specialized program? The two programs have different characteristics and different capabilities.
If it is being done to bridge two languages, then that sounds like a lack of interface library.
You say that as if having a universal-to-some-degree interface library would necessarily be a good thing. Perhaps it would, but in many cases such a library would be big and difficult to write and maintain, and maybe even slow. And if such a beast in fact does not exist to serve the particular problem at hand, then who are you to insist that one be created, when a code generation approach can solve the problem much more quickly and easily?
Am I missing something here?
Several things, I think.
I know that code is data as well. What I don't understand is, why generate source code? Why not make it into a function which can accept parameters and act on them?
Code generators transform code written in one language to code in a different, usually lower-level language. You're asking, then, why people would want to write programs using multiple languages, and especially why they might want to mix languages of subjectively different levels.
But I touched on that already. One chooses a language for a particular task based in part on its clarity and expressiveness for that task. Inasmuch as smaller code has fewer bugs on average and is easier to maintain, there is also a bias toward higher-level languages, at least for large-scale work. But a complex program involves many tasks, and often some of them can be more effectively addressed in one language, whereas others are more effectively or more concisely addressed in another. Using the right tool for the job sometimes means employing code generation.