Visual Basic

Generating Code

You select the code generation model you want via the somewhat hidden dialog box shown in Figure 7-1. You get to this dialog box by choosing Properties from the Project menu.

Figure 7-1 Visual Basic's compiler options dialog boxes

As you can see, some extra compilation options become available when you select Compile To Native Code. I'll discuss some of these options a little later.

When you compile to native code, the Visual Basic 6 native code generator/compiler, C2.EXE, is run once for each code component in the project. For example, if a project has a form, Form1; a standard module, Module1; and a class module, Class1; C2.EXE is run a total of three times. Each invocation's options are the same depending on which you selected in the dialog box; that is, the options you select are used to compile the entire project. In case you're interested, C2.EXE runs as a multithreaded, Win32, 32-bit console process.

Each time the native code compiler is run, a hidden process (described as 16-bit by the Windows 95 Task Manager) is started and the code generator/compiler, also run as a hidden process, is run attached to this process. (In Windows 95, this process is run from the file WINOA386.MOD, with a process description of "Non-Windows application component for 386 enhanced mode." This file is not required if you're running under Windows NT.) As each invocation of C2.EXE terminates, the instance of WINOLDAP (the module name given to WINOA386.MOD) in which it was run is also terminated. You should now start to see why this process might be slower than selecting p-code generation (which is an internal process and doesn't use C2.EXE, although it does use LINK.EXE). Here's what the command-line arguments of a typical compilation look like (with no optimizations):

C2 -il C:\WINDOWS\TEMP\VB603389 -f Form1 -W3 -Gy -G5 -Gs4096
  -dos -Zl -FoC:\TEMP\Form1.OBJ -QIfdiv -ML -basic

These flags are explained in Table 7-1.

Table 7-1. Command-line flags for the C2 Compiler

Flag Explanation
-il C:\WINDOWS\TEMP\VB603389 Undocumented but also used for C program; probably used to "name" intermediate language files
-f Form1 The input file to be compiled
-W3 Warning level 3
-Gy Enable function-level linking
-G5 Optimize for Pentium
-Gs4096 Turn off stack probes
-dos Undocumented but also used for a C program
-Zl Remove default library name from OBJ file
-Fo C:\TEMP\Form1.OBJ Name of output file
-QIfdiv Perform Pentium FDIV erratum fix
-ML Create a single-threaded executable file
-basic Undocumented but appears to be a new flag for Visual Basic compilation

Some of the flags are described in more detail here as well:

-il This flag is undocumented but "intermediate language" is a good guess for what "il" stands for. Files produced are <Signature>GL, SY, EX, IN, and DB. I have no idea what these files contain. In the command-line example in Table 7-1, the following files (long filenames shown) are generated temporarily while the application is being built:

  • VB603389GL
  • VB603389SY
  • VB603389EX
  • VB603389IN
  • VB603389DB

-G5 The option optimizes the generated code to favor the Intel Pentium processor. Here's what the Microsoft Developer Network (MSDN) says about the same Visual C++ flag: "Use this option for programs meant only for the Pentium. Code created using the /G5 option does not perform as well on 80386- and 80486-based computers as code created using the /GB (Blend) option." Interestingly, by default, the -G5 switch is always used-even when you compile on a 486 machine.

-Gs[size] If a function requires more than size stack space for local variables, its stack probe is activated. A stack probe is a piece of code that checks whether the space required for passed parameters and local variables is available on the stack before any attempt to allocate the space is made. -Gs0 is the same as -Ge, turn stack probes on; -Gs4096 is the default.

-ML This option places the library name LIBC.LIB in the object file so that the linker will use LIBC.LIB to resolve external symbols. This is the compiler's default action. LIBC.LIB does not provide multithread support, by the way.

Don't bother to scan your Visual Basic 6 documentation for information about these flags because you won't find any-they are all undocumented. If you have a set of documentation for the Visual C++ compiler, however, you might be in luck. It seems that C2.EXE is taken from the Visual C++ compiler (this file is called C2.DLL in version 6 of Visual C++, although in Visual Basic 5, both Visual Basic and Visual C++ shared exactly the same file-C2.EXE). C2.EXE is, in fact, the compiler from Microsoft's Visual C++ product. Nevertheless, the above interpretation of the flag meanings is mine alone. Microsoft doesn't document how its C++ compiler works beyond describing CL.EXE (the front end to the C compiler).

Table 7-2. Comparison of Visual C++ and Visual Basic C2 Components

Component Product Version Compiler Description
C2.EXE (from Visual Basic 6) 6.0.8041.0 32-Bit 80x86 Compiler Back End
C2.DLL (from Visual C++ 6) 6.0.8168.0 32-Bit 80x86 Compiler Back End
C2.EXE (from Visual Basic 5) 5.0.0.7182 32-bit Visual Basic Compiler Back End

Visual Basic itself evidently provides the compiler's first pass, unlike Visual C++ in which the first pass (the parser and some of the optimizer) of C and C++ files is provided by either C1.DLL or C1XX.DLL, respectively. In terms of compilers, VB6.EXE is seemingly analogous to CL.EXE.