* Simplify TargetRegisterClass implementations
[oota-llvm.git] / lib / Target / X86 / README.txt
index c310bff9380b5181a7fce505631ec8fd7119fdfb..956859ba5d89ba2e9d86cefae97571a9279068ef 100644 (file)
@@ -25,68 +25,134 @@ implementation notes, design decisions, and other stuff.
 II. Architecture / Design Decisions
 ===================================
 
-We designed the infrastructure for the machine specific representation to be as
-light-weight as possible, while also being able to support as many targets as
-possible with our framework.  This framework should allow us to share many
-common machine specific transformations (register allocation, instruction
-scheduling, etc...) among all of the backends that may eventually be supported
-by the JIT, and unify the JIT and static compiler backends.
+We designed the infrastructure into the generic LLVM machine specific
+representation, which allows us to support as many targets as possible with our
+framework.  This framework should allow us to share many common machine specific
+transformations (register allocation, instruction scheduling, etc...) among all
+of the backends that may eventually be supported by LLVM, and ensures that the
+JIT and static compiler backends are largely shared.
 
 At the high-level, LLVM code is translated to a machine specific representation
-formed out of MFunction, MBasicBlock, and MInstruction instances (defined in
-include/llvm/CodeGen).  This representation is completely target agnostic,
-representing instructions in their most abstract form: an opcode, a destination,
-and a series of operands.  This representation is designed to support both SSA
-representation for machine code, as well as a register allocated, non-SSA form.
-
-Because the M* representation must work regardless of the target machine, it
-contains very little semantic information about the program.  To get semantic
+formed out of MachineFunction, MachineBasicBlock, and MachineInstr instances
+(defined in include/llvm/CodeGen).  This representation is completely target
+agnostic, representing instructions in their most abstract form: an opcode, a
+destination, and a series of operands.  This representation is designed to
+support both SSA representation for machine code, as well as a register
+allocated, non-SSA form.
+
+Because the Machine* representation must work regardless of the target machine,
+it contains very little semantic information about the program.  To get semantic
 information about the program, a layer of Target description datastructures are
 used, defined in include/llvm/Target.
 
-Currently the Sparc backend and the X86 backend do not share a common
-representation.  This is an intentional decision, and will be rectified in the
-future (after the project is done).
-
-
-=======================
-III. Source Code Layout
-=======================
+Note that there is some amount of complexity that the X86 backend contains due
+to the Sparc backend's legacy requirements.  These should eventually fade away
+as the project progresses.
+
+
+SSA Instruction Representation
+------------------------------
+Target machine instructions are represented as instances of MachineInstr, and
+all specific machine instruction types should have an entry in the
+InstructionInfo table defined through X86InstrInfo.def.  In the X86 backend,
+there are two particularly interesting forms of machine instruction: those that
+produce a value (such as add), and those that do not (such as a store).
+
+Instructions that produce a value use Operand #0 as the "destination" register.
+When printing the assembly code with the built-in machine instruction printer,
+these destination registers will be printed to the left side of an '=' sign, as
+in: %reg1027 = addl %reg1026, %reg1025
+
+This 'addl' MachineInstruction contains three "operands": the first is the
+destination register (#1027), the second is the first source register (#1026)
+and the third is the second source register (#1025).  Never forget the
+destination register will show up in the MachineInstr operands vector.  The code
+to generate this instruction looks like this:
+
+  BuildMI(BB, X86::ADDrr32, 2, 1027).addReg(1026).addReg(1025);
+
+The first argument to BuildMI is the basic block to append the machine
+instruction to, the second is the opcode, the third is the number of operands,
+the fourth is the destination register.  The two addReg calls specify operands
+in order.
+
+MachineInstrs that do not produce a value do not have this implicit first
+operand, they simply have #operands = #uses.  To create them, simply do not
+specify a destination register to the BuildMI call.
+
+
+======================================
+III. Lazy Function Resolution in Jello
+======================================
+
+Jello is a designed to be a JIT compiler for LLVM code.  This implies that call
+instructions may be emitted before the function they call is compiled.  In order
+to support this, Jello currently emits unresolved call instructions to call to a
+null pointer.  When the call instruction is executed, a segmentation fault will
+be generated.
+
+Jello installs a trap handler for SIGSEGV, in order to trap these events.  When
+a SIGSEGV occurs, first we check to see if it's due to lazy function resolution,
+if so, we look up the return address of the function call (which was pushed onto
+the stack by the call instruction).  Given the return address of the call, we
+consult a map to figure out which function was supposed to be called from that
+location.
+
+If the function has not been code generated yet, it is at this time.  Finally,
+the EIP of the process is modified to point to the real function address, the
+original call instruction is updated, and the SIGSEGV handler returns, causing
+execution to start in the called function.  Because we update the original call
+instruction, we should only get at most one signal for each call site.
+
+Note that this approach does not work for indirect calls.  The problem with
+indirect calls is that taking the address of a function would not cause a fault
+(it would simply copy null into a register), so we would only find out about the
+problem when the indirect call itself was made.  At this point we would have no
+way of knowing what the intended function destination was.  Because of this, we
+immediately code generate functions whenever they have their address taken,
+side-stepping the problem completely.
+
+
+======================
+IV. Source Code Layout
+======================
 
 The LLVM-JIT is composed of source files primarily in the following locations:
 
 include/llvm/CodeGen
 --------------------
-
 This directory contains header files that are used to represent the program in a
 machine specific representation.  It currently also contains a bunch of stuff
-used by the Sparc backend that we don't want to get mixed up in.
+used by the Sparc backend that we don't want to get mixed up in, such as
+register allocation internals.
 
 include/llvm/Target
 -------------------
-
 This directory contains header files that are used to interpret the machine
 specific representation of the program.  This allows us to write generic
 transformations that will work on any target that implements the interfaces
-defined in this directory.  Again, this also contains a bunch of stuff from the
-Sparc Backend that we don't want to deal with.
+defined in this directory.  The only classes used by the X86 backend so far are
+the TargetMachine, TargetData, MachineInstrInfo, and MRegisterInfo classes.
 
 lib/CodeGen
 -----------
-This directory will contain all of the target independant transformations (for
+This directory will contain all of the target independent transformations (for
 example, register allocation) that we write.  These transformations should only
-use information exposed through the Target interface, it should not include any
-target specific header files.
+use information exposed through the Target interface, they should not include
+any target specific header files.
 
 lib/Target/X86
 --------------
 This directory contains the machine description for X86 that is required to the
-rest of the compiler working.  It contains any code that is truely specific to
+rest of the compiler working.  It contains any code that is truly specific to
 the X86 backend, for example the instruction selector and machine code emitter.
 
 tools/jello
 -----------
-This directory contains the top-level code for the JIT compiler.
+This directory contains the top-level code for the JIT compiler.  This code
+basically boils down to a call to TargetMachine::addPassesToJITCompile.  As we
+progress with the project, this will also contain the compile-dispatch-recompile
+loop.
 
 test/Regression/Jello
 ---------------------
@@ -94,24 +160,41 @@ This directory contains regression tests for the JIT.  Initially it contains a
 bunch of really trivial testcases that we should build up to supporting.
 
 
+==================================================
+V. Strange Things, or, Things That Should Be Known
+==================================================
+
+Representing memory in MachineInstrs
+------------------------------------
+
+The x86 has a very, uhm, flexible, way of accessing memory.  It is capable of
+addressing memory addresses of the following form directly in integer
+instructions (which use ModR/M addressing):
+
+   Base+[1,2,4,8]*IndexReg+Disp32
+
+Wow, that's crazy.  In order to represent this, LLVM tracks no less that 4
+operands for each memory operand of this form.  This means that the "load" form
+of 'mov' has the following "Operands" in this order:
+
+Index:        0     |    1        2       3           4
+Meaning:   DestReg, | BaseReg,  Scale, IndexReg, Displacement
+OperandTy: VirtReg, | VirtReg, UnsImm, VirtReg,   SignExtImm
+
+Stores and all other instructions treat the four memory operands in the same
+way, in the same order.
+
+
 ==========================
-IV. TODO / Future Projects
+VI. TODO / Future Projects
 ==========================
 
 There are a large number of things remaining to do.  Here is a partial list:
 
-Critial path:
+Critical path:
 -------------
 
-0. Finish providing SSA form.  This involves keeping track of some information
-   when instructions are added to the function, but should not affect that API
-   for creating new MInstructions or adding them to the program.  There are
-   also various FIXMEs in the M* files that need to get taken care of in the
-   near term.
 1. Finish dumb instruction selector
-2. Write dumb register allocator
-3. Write assembly language emitter
-4. Write machine code emitter
 
 Next Phase:
 -----------
@@ -121,23 +204,23 @@ Next Phase:
 After this project:
 -------------------
 1. Implement lots of nifty runtime optimizations
-2. Implement a static compiler backend for x86
-3. Migrate Sparc backend to new representation
-4. Implement new spiffy targets: IA64? X86-64? M68k?  Who knows...
+2. Implement a static compiler backend for x86 (might come almost for free...)
+3. Implement new targets: IA64? X86-64? M68k?  Who knows...
 
 Infrastructure Improvements:
 ----------------------------
 
 1. Bytecode is designed to be able to read particular functions from the
    bytecode without having to read the whole program.  Bytecode reader should be
-   extended to allow on demand loading of functions.
+   extended to allow on-demand loading of functions.
 
 2. PassManager needs to be able to run just a single function through a pipeline
-   of FunctionPass's.  When this happens, all of our code will become
-   FunctionPass's for real.
+   of FunctionPass's.
 
 3. llvmgcc needs to be modified to output 32-bit little endian LLVM files.
    Preferably it will be parameterizable so that multiple binaries need not
    exist.  Until this happens, we will be restricted to using type safe
    programs (most of the Olden suite and many smaller tests), which should be
-   sufficient for our 497 project.
+   sufficient for our 497 project.  Additionally there are a few places in the
+   LLVM infrastructure where we assume Sparc TargetData layout.  These should
+   be easy to factor out and identify though.