mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-02 22:23:10 +00:00
Convert backend to use passes, implement X86TargetMachine
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@4421 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -10,28 +10,32 @@
|
|||||||
#include "llvm/iTerminators.h"
|
#include "llvm/iTerminators.h"
|
||||||
#include "llvm/Type.h"
|
#include "llvm/Type.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/Support/InstVisitor.h"
|
#include "llvm/Support/InstVisitor.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ISel : public InstVisitor<ISel> { // eventually will be a FunctionPass
|
struct ISel : public FunctionPass, InstVisitor<ISel> {
|
||||||
|
TargetMachine &TM;
|
||||||
MachineFunction *F; // The function we are compiling into
|
MachineFunction *F; // The function we are compiling into
|
||||||
MachineBasicBlock *BB; // The current MBB we are compiling
|
MachineBasicBlock *BB; // The current MBB we are compiling
|
||||||
|
|
||||||
unsigned CurReg;
|
unsigned CurReg;
|
||||||
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
|
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
|
||||||
|
|
||||||
ISel(MachineFunction *f)
|
ISel(TargetMachine &tm)
|
||||||
: F(f), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}
|
: TM(tm), F(0), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}
|
||||||
|
|
||||||
/// runOnFunction - Top level implementation of instruction selection for
|
/// runOnFunction - Top level implementation of instruction selection for
|
||||||
/// the entire function.
|
/// the entire function.
|
||||||
///
|
///
|
||||||
bool runOnFunction(Function &F) {
|
bool runOnFunction(Function &Fn) {
|
||||||
visit(F);
|
F = new MachineFunction(&Fn, TM);
|
||||||
|
visit(Fn);
|
||||||
RegMap.clear();
|
RegMap.clear();
|
||||||
|
F = 0;
|
||||||
return false; // We never modify the LLVM itself.
|
return false; // We never modify the LLVM itself.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,14 +165,10 @@ void ISel::visitAdd(BinaryOperator &B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
||||||
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
||||||
/// X86SimpleInstructionSelection - This function converts an LLVM function into
|
|
||||||
/// a machine code representation is a very simple peep-hole fashion. The
|
|
||||||
/// generated code sucks but the implementation is nice and simple.
|
/// generated code sucks but the implementation is nice and simple.
|
||||||
///
|
///
|
||||||
MachineFunction *X86SimpleInstructionSelection(Function &F, TargetMachine &TM) {
|
Pass *createSimpleX86InstructionSelector(TargetMachine &TM) {
|
||||||
MachineFunction *Result = new MachineFunction(&F, TM);
|
return new ISel(TM);
|
||||||
ISel(Result).runOnFunction(F);
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,37 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "X86.h"
|
#include "X86.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
/// X86PrintCode - Print out the specified machine code function to the
|
namespace {
|
||||||
/// specified stream. This function should work regardless of whether or not
|
struct Printer : public FunctionPass {
|
||||||
/// the function is in SSA form or not, although when in SSA form, we obviously
|
TargetMachine &TM;
|
||||||
/// don't care about being consumable by an assembler.
|
std::ostream &O;
|
||||||
///
|
|
||||||
void X86PrintCode(const MachineFunction *MF, std::ostream &O) {
|
|
||||||
O << "x86 printing not implemented yet!\n";
|
|
||||||
|
|
||||||
// This should use the X86InstructionInfo::print method to print assembly for
|
Printer(TargetMachine &tm, std::ostream &o) : TM(tm), O(o) {}
|
||||||
// each instruction
|
|
||||||
|
bool runOnFunction(Function &F);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Printer::runOnFunction(Function &F) {
|
||||||
|
MachineFunction &MF = MachineFunction::get(&F);
|
||||||
|
O << "x86 printing not implemented yet!\n";
|
||||||
|
|
||||||
|
// This should use the X86InstructionInfo::print method to print assembly
|
||||||
|
// for each instruction
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// createX86CodePrinterPass - Print out the specified machine code function to
|
||||||
|
/// the specified stream. This function should work regardless of whether or
|
||||||
|
/// not the function is in SSA form or not.
|
||||||
|
///
|
||||||
|
Pass *createX86CodePrinterPass(TargetMachine &TM, std::ostream &O) {
|
||||||
|
return new Printer(TM, O);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,34 +11,32 @@
|
|||||||
#define TARGET_X86_H
|
#define TARGET_X86_H
|
||||||
|
|
||||||
#include <iosfwd>
|
#include <iosfwd>
|
||||||
class MachineFunction;
|
|
||||||
class Function;
|
|
||||||
class TargetMachine;
|
class TargetMachine;
|
||||||
|
class Pass;
|
||||||
|
|
||||||
/// X86PrintCode - Print out the specified machine code function to the
|
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
||||||
/// specified stream. This function should work regardless of whether or not
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
||||||
/// the function is in SSA form or not.
|
|
||||||
///
|
|
||||||
void X86PrintCode(const MachineFunction *MF, std::ostream &O);
|
|
||||||
|
|
||||||
/// X86SimpleInstructionSelection - This function converts an LLVM function into
|
|
||||||
/// a machine code representation is a very simple peep-hole fashion. The
|
|
||||||
/// generated code sucks but the implementation is nice and simple.
|
/// generated code sucks but the implementation is nice and simple.
|
||||||
///
|
///
|
||||||
MachineFunction *X86SimpleInstructionSelection(Function &F, TargetMachine &TM);
|
Pass *createSimpleX86InstructionSelector(TargetMachine &TM);
|
||||||
|
|
||||||
/// X86SimpleRegisterAllocation - This function converts the specified machine
|
/// X86SimpleRegisterAllocation - This function converts the specified machine
|
||||||
/// code function from SSA form to use explicit registers by spilling every
|
/// code function from SSA form to use explicit registers by spilling every
|
||||||
/// register. Wow, great policy huh?
|
/// register. Wow, great policy huh?
|
||||||
///
|
///
|
||||||
inline void X86SimpleRegisterAllocation(MachineFunction *MF) {}
|
Pass *createSimpleX86RegisterAllocator(TargetMachine &TM);
|
||||||
|
|
||||||
|
/// createX86CodePrinterPass - Print out the specified machine code function to
|
||||||
|
/// the specified stream. This function should work regardless of whether or
|
||||||
|
/// not the function is in SSA form or not.
|
||||||
|
///
|
||||||
|
Pass *createX86CodePrinterPass(TargetMachine &TM, std::ostream &O);
|
||||||
|
|
||||||
/// X86EmitCodeToMemory - This function converts a register allocated function
|
/// X86EmitCodeToMemory - This function converts a register allocated function
|
||||||
/// into raw machine code in a dynamically allocated chunk of memory. A pointer
|
/// into raw machine code in a dynamically allocated chunk of memory. A pointer
|
||||||
/// to the start of the function is returned.
|
/// to the start of the function is returned.
|
||||||
///
|
///
|
||||||
inline void *X86EmitCodeToMemory(MachineFunction *MF) { return 0; }
|
Pass *createEmitX86CodeToMemory(TargetMachine &TM);
|
||||||
|
|
||||||
|
|
||||||
// Put symbolic names in a namespace to avoid causing these to clash with all
|
// Put symbolic names in a namespace to avoid causing these to clash with all
|
||||||
// kinds of other things...
|
// kinds of other things...
|
||||||
|
|||||||
@@ -6,16 +6,37 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "X86.h"
|
#include "X86.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
/// X86PrintCode - Print out the specified machine code function to the
|
namespace {
|
||||||
/// specified stream. This function should work regardless of whether or not
|
struct Printer : public FunctionPass {
|
||||||
/// the function is in SSA form or not, although when in SSA form, we obviously
|
TargetMachine &TM;
|
||||||
/// don't care about being consumable by an assembler.
|
std::ostream &O;
|
||||||
///
|
|
||||||
void X86PrintCode(const MachineFunction *MF, std::ostream &O) {
|
|
||||||
O << "x86 printing not implemented yet!\n";
|
|
||||||
|
|
||||||
// This should use the X86InstructionInfo::print method to print assembly for
|
Printer(TargetMachine &tm, std::ostream &o) : TM(tm), O(o) {}
|
||||||
// each instruction
|
|
||||||
|
bool runOnFunction(Function &F);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Printer::runOnFunction(Function &F) {
|
||||||
|
MachineFunction &MF = MachineFunction::get(&F);
|
||||||
|
O << "x86 printing not implemented yet!\n";
|
||||||
|
|
||||||
|
// This should use the X86InstructionInfo::print method to print assembly
|
||||||
|
// for each instruction
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/// createX86CodePrinterPass - Print out the specified machine code function to
|
||||||
|
/// the specified stream. This function should work regardless of whether or
|
||||||
|
/// not the function is in SSA form or not.
|
||||||
|
///
|
||||||
|
Pass *createX86CodePrinterPass(TargetMachine &TM, std::ostream &O) {
|
||||||
|
return new Printer(TM, O);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,28 +10,32 @@
|
|||||||
#include "llvm/iTerminators.h"
|
#include "llvm/iTerminators.h"
|
||||||
#include "llvm/Type.h"
|
#include "llvm/Type.h"
|
||||||
#include "llvm/Constants.h"
|
#include "llvm/Constants.h"
|
||||||
|
#include "llvm/Pass.h"
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
#include "llvm/CodeGen/MachineFunction.h"
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
||||||
#include "llvm/Support/InstVisitor.h"
|
#include "llvm/Support/InstVisitor.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct ISel : public InstVisitor<ISel> { // eventually will be a FunctionPass
|
struct ISel : public FunctionPass, InstVisitor<ISel> {
|
||||||
|
TargetMachine &TM;
|
||||||
MachineFunction *F; // The function we are compiling into
|
MachineFunction *F; // The function we are compiling into
|
||||||
MachineBasicBlock *BB; // The current MBB we are compiling
|
MachineBasicBlock *BB; // The current MBB we are compiling
|
||||||
|
|
||||||
unsigned CurReg;
|
unsigned CurReg;
|
||||||
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
|
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
|
||||||
|
|
||||||
ISel(MachineFunction *f)
|
ISel(TargetMachine &tm)
|
||||||
: F(f), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}
|
: TM(tm), F(0), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}
|
||||||
|
|
||||||
/// runOnFunction - Top level implementation of instruction selection for
|
/// runOnFunction - Top level implementation of instruction selection for
|
||||||
/// the entire function.
|
/// the entire function.
|
||||||
///
|
///
|
||||||
bool runOnFunction(Function &F) {
|
bool runOnFunction(Function &Fn) {
|
||||||
visit(F);
|
F = new MachineFunction(&Fn, TM);
|
||||||
|
visit(Fn);
|
||||||
RegMap.clear();
|
RegMap.clear();
|
||||||
|
F = 0;
|
||||||
return false; // We never modify the LLVM itself.
|
return false; // We never modify the LLVM itself.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,14 +165,10 @@ void ISel::visitAdd(BinaryOperator &B) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// createSimpleX86InstructionSelector - This pass converts an LLVM function
|
||||||
|
/// into a machine code representation is a very simple peep-hole fashion. The
|
||||||
/// X86SimpleInstructionSelection - This function converts an LLVM function into
|
|
||||||
/// a machine code representation is a very simple peep-hole fashion. The
|
|
||||||
/// generated code sucks but the implementation is nice and simple.
|
/// generated code sucks but the implementation is nice and simple.
|
||||||
///
|
///
|
||||||
MachineFunction *X86SimpleInstructionSelection(Function &F, TargetMachine &TM) {
|
Pass *createSimpleX86InstructionSelector(TargetMachine &TM) {
|
||||||
MachineFunction *Result = new MachineFunction(&F, TM);
|
return new ISel(TM);
|
||||||
ISel(Result).runOnFunction(F);
|
|
||||||
return Result;
|
|
||||||
}
|
}
|
||||||
|
|||||||
43
lib/Target/X86/X86TargetMachine.cpp
Normal file
43
lib/Target/X86/X86TargetMachine.cpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//===-- X86TargetMachine.cpp - Define TargetMachine for the X86 -----------===//
|
||||||
|
//
|
||||||
|
// This file defines the X86 specific subclass of TargetMachine.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#include "X86TargetMachine.h"
|
||||||
|
#include "llvm/Target/TargetMachineImpls.h"
|
||||||
|
#include "llvm/PassManager.h"
|
||||||
|
#include "X86.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
// allocateX86TargetMachine - Allocate and return a subclass of TargetMachine
|
||||||
|
// that implements the X86 backend.
|
||||||
|
//
|
||||||
|
TargetMachine *allocateX86TargetMachine() { return new X86TargetMachine(); }
|
||||||
|
|
||||||
|
|
||||||
|
/// X86TargetMachine ctor - Create an ILP32 architecture model
|
||||||
|
///
|
||||||
|
X86TargetMachine::X86TargetMachine() : TargetMachine("X86", 1, 4, 4, 4) {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// addPassesToJITCompile - Add passes to the specified pass manager to
|
||||||
|
/// implement a fast dynamic compiler for this target. Return true if this is
|
||||||
|
/// not supported for this target.
|
||||||
|
///
|
||||||
|
bool X86TargetMachine::addPassesToJITCompile(PassManager &PM) {
|
||||||
|
PM.add(createSimpleX86InstructionSelector(*this));
|
||||||
|
|
||||||
|
// TODO: optional optimizations go here
|
||||||
|
|
||||||
|
// Perform register allocation to convert to a concrete x86 representation
|
||||||
|
//PM.add(createSimpleX86RegisterAllocator(*this));
|
||||||
|
|
||||||
|
PM.add(createX86CodePrinterPass(*this, std::cerr));
|
||||||
|
|
||||||
|
//PM.add(createEmitX86CodeToMemory(*this));
|
||||||
|
|
||||||
|
return false; // success!
|
||||||
|
}
|
||||||
|
|
||||||
32
lib/Target/X86/X86TargetMachine.h
Normal file
32
lib/Target/X86/X86TargetMachine.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
//===-- X86TargetMachine.h - Define TargetMachine for the X86 ---*- C++ -*-===//
|
||||||
|
//
|
||||||
|
// This file declares the X86 specific subclass of TargetMachine.
|
||||||
|
//
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
#ifndef X86TARGETMACHINE_H
|
||||||
|
#define X86TARGETMACHINE_H
|
||||||
|
|
||||||
|
#include "llvm/Target/TargetMachine.h"
|
||||||
|
#include "X86InstrInfo.h"
|
||||||
|
|
||||||
|
class X86TargetMachine : public TargetMachine {
|
||||||
|
X86InstrInfo instrInfo;
|
||||||
|
public:
|
||||||
|
X86TargetMachine();
|
||||||
|
|
||||||
|
virtual const MachineInstrInfo &getInstrInfo() const { return instrInfo; }
|
||||||
|
virtual const MachineSchedInfo &getSchedInfo() const { abort(); }
|
||||||
|
virtual const MachineRegInfo &getRegInfo() const { abort(); }
|
||||||
|
virtual const MachineFrameInfo &getFrameInfo() const { abort(); }
|
||||||
|
virtual const MachineCacheInfo &getCacheInfo() const { abort(); }
|
||||||
|
virtual const MachineOptInfo &getOptInfo() const { abort(); }
|
||||||
|
|
||||||
|
/// addPassesToJITCompile - Add passes to the specified pass manager to
|
||||||
|
/// implement a fast dynamic compiler for this target. Return true if this is
|
||||||
|
/// not supported for this target.
|
||||||
|
///
|
||||||
|
virtual bool addPassesToJITCompile(PassManager &PM);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user