2004-04-06 19:31:31 +00:00
//===- SimpleInstrSelEmitter.cpp - Generate a Simple Instruction Selector ------------===//
//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This tablegen backend is responsible for emitting an instruction selector
//
//
//===----------------------------------------------------------------------===//
# include "InstrInfoEmitter.h"
# include "SimpleInstrSelEmitter.h"
# include "CodeGenWrappers.h"
# include "Record.h"
# include "Support/Debug.h"
# include "Support/StringExtras.h"
# include <set>
# include "Record.h"
# include "Support/CommandLine.h"
2004-05-27 05:41:36 +00:00
# include "llvm/System/Signals.h"
2004-04-06 19:31:31 +00:00
# include "Support/FileUtilities.h"
# include "CodeEmitterGen.h"
# include "RegisterInfoEmitter.h"
# include "InstrInfoEmitter.h"
# include "InstrSelectorEmitter.h"
# include "SimpleInstrSelEmitter.h"
# include <algorithm>
# include <cstdio>
# include <fstream>
# include <vector>
namespace llvm {
std : : string FnDecs ;
// run - Emit the main instruction description records for the target...
void SimpleInstrSelEmitter : : run ( std : : ostream & OS ) {
// EmitSourceFileHeader("Mark's Instruction Selector for the X86 target", OS);
// OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
// OS << "#include \"llvm/Constants.h\"\n";
// OS << "#include \"llvm/DerivedTypes.h\"\n";
// OS << "#include \"llvm/Function.h\"\n";
// OS << "#include \"llvm/Instructions.h\"\n";
// OS << "#include \"llvm/Pass.h\"\n";
2004-06-20 07:49:54 +00:00
// OS << "#include \"llvm/CodeGen/IntrinsicLowering.h\"\n";
2004-04-06 19:31:31 +00:00
// OS << "#include \"llvm/CodeGen/MachineConstantPool.h\"\n";
// OS << "#include \"llvm/CodeGen/MachineFrameInfo.h\"\n";
// OS << "#include \"llvm/CodeGen/MachineFunction.h\"\n";
// OS << "#include \"llvm/CodeGen/MachineInstrBuilder.h\"\n";
// OS << "#include \"llvm/CodeGen/SSARegMap.h\"\n";
// OS << "#include \"llvm/Target/MRegisterInfo.h\"\n";
// OS << "#include \"llvm/Target/TargetMachine.h\"\n";
// OS << "#include \"llvm/Support/InstVisitor.h\"\n";
// OS << "using namespace llvm;\n\n";
FnDecs = " " ;
// for each InstrClass
std : : vector < Record * > Recs = Records . getAllDerivedDefinitions ( " InstrClass " ) ;
for ( unsigned i = 0 , e = Recs . size ( ) ; i ! = e ; + + i ) {
std : : string InstrClassName = Recs [ i ] - > getName ( ) ;
OS < < " // Generate BMI instructions for " < < InstrClassName < < " \n \n " ;
OS < < " void ISel::visit " ;
OS < < Recs [ i ] - > getValueAsString ( " FunctionName " ) ;
OS < < " ( " < < Recs [ i ] - > getValueAsString ( " InstructionName " ) < < " &I) \n { " < < " \n " ;
// for each supported InstrSubclass
OS < < spacing ( ) < < " unsigned DestReg = getReg(I); \n " ;
OS < < spacing ( ) < < " unsigned Op0Reg = getReg(I.getOperand(0)); \n " ;
OS < < spacing ( ) < < " unsigned Op1Reg = getReg(I.getOperand(1)); \n " ;
OS < < spacing ( ) < < " Value *Op0Val = I.getOperand(0); \n " ;
OS < < spacing ( ) < < " Value *Op1Val = I.getOperand(1); \n " ;
OS < < spacing ( ) < < " MachineBasicBlock::iterator IP = BB->end(); \n " ;
OS < < std : : endl ;
ListInit * SupportedSubclasses = Recs [ i ] - > getValueAsListInit ( " Supports " ) ;
//OS << spacing() << InstrClassName << "Prep();" << "\n";
//FnDecs += "void ISel::" + InstrClassName + "Prep() {\n\n}\n\n";
std : : vector < std : : string > vi ;
// generate subclasses nested switch statements
InstrSubclasses ( OS , InstrClassName , InstrClassName , SupportedSubclasses , vi , 0 ) ;
//OS << spacing() << InstrClassName << "Post();\n";
//FnDecs += "void ISel::" + InstrClassName + "Post() {\n\n}\n\n";
OS < < " } \n " ;
OS < < " \n \n \n " ;
} // for each instrclass
// OS << "} //namespace\n";
#if 0
// print out function stubs
OS < < " \n \n \n //Functions \n \n " < < FnDecs ;
// print out getsubclass() definitions
std : : vector < Record * > SubclassColRec = Records . getAllDerivedDefinitions ( " InstrSubclassCollection " ) ;
for ( unsigned j = 0 , m = SubclassColRec . getSize ( ) ; j ! = m ; + + j ) {
std : : string SubclassName = SubclassColRec [ j ] - > getName ( ) ;
FnDecs + = " unsigned ISel::get " + SubclassName + " () { \n \n " ;
ListInit * list = dynamic_cast < ListInit * > ( SubclassColRec [ j ] . getValueAsListInit ( " List " ) ) ;
for ( unsigned k = 0 ; n = list . getSize ( ) ; k ! = n ; + + k ) {
FnDecs + = " } \n \n " ;
}
# endif
} //run
// find instructions that match all the subclasses (only support for 1 now)
Record * SimpleInstrSelEmitter : : findInstruction ( std : : ostream & OS , std : : string cl , std : : vector < std : : string > & vi ) {
std : : vector < Record * > Recs = Records . getAllDerivedDefinitions ( " TargInstrSet " ) ;
for ( unsigned i = 0 , e = Recs . size ( ) ; i ! = e ; + + i ) {
Record * thisClass = Recs [ i ] - > getValueAsDef ( " Class " ) ;
if ( thisClass - > getName ( ) = = cl ) {
// get the Subclasses this supports
ListInit * SubclassList = Recs [ i ] - > getValueAsListInit ( " List " ) ;
bool Match = true ;
if ( SubclassList - > getSize ( ) ! = vi . size ( ) )
Match = false ;
// match the instruction's supported subclasses with the subclasses we are looking for
for ( unsigned j = 0 , f = SubclassList - > getSize ( ) ; j ! = f ; + + j ) {
DefInit * SubclassDef = dynamic_cast < DefInit * > ( SubclassList - > getElement ( j ) ) ;
Record * thisSubclass = SubclassDef - > getDef ( ) ;
std : : string searchingFor = vi [ j ] ;
if ( thisSubclass - > getName ( ) ! = searchingFor ) {
Match = false ;
}
} // for each subclass list
if ( Match = = true ) { return Recs [ i ] ; }
} //if instrclass matches
} // for all instructions
// if no instructions found, return NULL
return NULL ;
} //findInstruction
Record * SimpleInstrSelEmitter : : findRegister ( std : : ostream & OS , std : : string regname ) {
std : : vector < Record * > Recs = Records . getAllDerivedDefinitions ( " Register " ) ;
for ( unsigned i = 0 , e = Recs . size ( ) ; i ! = e ; + + i ) {
Record * thisReg = Recs [ i ] ;
if ( thisReg - > getName ( ) = = regname ) return Recs [ i ] ;
}
return NULL ;
}
// handle "::" and "+" etc
std : : string SimpleInstrSelEmitter : : formatRegister ( std : : ostream & OS , std : : string regname ) {
std : : string Reg ;
std : : string suffix ;
int x = std : : strcspn ( regname . c_str ( ) , " +- " ) ;
// operate on text before "+" or "-", append it back at the end
Reg = regname . substr ( 0 , x ) ;
suffix = regname . substr ( x , regname . length ( ) ) ;
unsigned int y = std : : strcspn ( Reg . c_str ( ) , " : " ) ;
if ( y = = Reg . length ( ) ) { // does not contain "::"
Record * RegRec = findRegister ( OS , Reg ) ;
assert ( RegRec & & " Register not found! " ) ;
if ( RegRec - > getValueAsString ( " Namespace " ) ! = " Virtual " ) {
Reg = RegRec - > getValueAsString ( " Namespace " ) + " :: " + RegRec - > getName ( ) ;
} else {
Reg = RegRec - > getName ( ) ;
}
} // regular case
// append + or - at the end again (i.e. X86::EAX+1)
Reg = Reg + suffix ;
return Reg ;
}
// take information in the instruction class and generate the correct BMI call
void SimpleInstrSelEmitter : : generateBMIcall ( std : : ostream & OS , std : : string MBB , std : : string IP , std : : string Opcode , int NumOperands , ListInit & instroperands , ListInit & operands ) {
// find Destination Register
StringInit * DestRegStr = dynamic_cast < StringInit * > ( operands . getElement ( 0 ) ) ;
std : : string DestReg = formatRegister ( OS , DestRegStr - > getValue ( ) ) ;
OS < < " BuildMI( " ;
OS < < MBB < < " , " ;
OS < < IP < < " , " ;
OS < < Opcode < < " , " ;
OS < < NumOperands ;
if ( DestReg ! = " Pseudo " ) {
OS < < " , " < < DestReg < < " ) " ;
} else {
OS < < " ) " ;
}
// handle the .add stuff
for ( unsigned i = 0 , e = instroperands . getSize ( ) ; i ! = e ; + + i ) {
DefInit * OpDef = dynamic_cast < DefInit * > ( instroperands . getElement ( i ) ) ;
StringInit * RegStr = dynamic_cast < StringInit * > ( operands . getElement ( i + 1 ) ) ;
Record * Op = OpDef - > getDef ( ) ;
std : : string opstr = Op - > getValueAsString ( " Name " ) ;
std : : string regname ;
if ( opstr = = " Register " ) {
regname = formatRegister ( OS , RegStr - > getValue ( ) ) ;
} else {
regname = RegStr - > getValue ( ) ;
}
OS < < " .add " < < opstr < < " ( " < < regname < < " ) " ;
}
OS < < " ; \n " ;
} //generateBMIcall
std : : string SimpleInstrSelEmitter : : spacing ( ) {
return globalSpacing ;
}
std : : string SimpleInstrSelEmitter : : addspacing ( ) {
globalSpacing + = " " ;
return globalSpacing ;
}
std : : string SimpleInstrSelEmitter : : remspacing ( ) {
globalSpacing = globalSpacing . substr ( 0 , globalSpacing . length ( ) - 2 ) ;
return globalSpacing ;
}
// recursively print out the subclasses of an instruction
//
void SimpleInstrSelEmitter : : InstrSubclasses ( std : : ostream & OS , std : : string prefix , std : : string InstrClassName , ListInit * SupportedSubclasses , std : : vector < std : : string > & vi , unsigned depth ) {
if ( depth > = SupportedSubclasses - > getSize ( ) ) {
return ;
}
// get the subclass collection
DefInit * InstrSubclassColl = dynamic_cast < DefInit * > ( SupportedSubclasses - > getElement ( depth ) ) ;
Record * InstrSubclassRec = InstrSubclassColl - > getDef ( ) ;
std : : string SubclassName = InstrSubclassRec - > getName ( ) ;
if ( InstrSubclassRec - > getValueAsString ( " PreCode " ) ! = " " ) {
// OS << spacing() << prefix << "_" << Subclass->getName() << "_Prep();\n";
OS < < spacing ( ) < < InstrSubclassRec - > getValueAsString ( " PreCode " ) < < " \n \n " ;
}
OS < < spacing ( ) < < " // Looping through " < < SubclassName < < " \n " ;
OS < < spacing ( ) < < " switch ( " < < SubclassName < < " ) { \n " ;
addspacing ( ) ;
ListInit * SubclassList = InstrSubclassRec - > getValueAsListInit ( " List " ) ;
for ( unsigned k = 0 , g = SubclassList - > getSize ( ) ; k ! = g ; + + k ) {
DefInit * SubclassDef = dynamic_cast < DefInit * > ( SubclassList - > getElement ( k ) ) ;
Record * Subclass = SubclassDef - > getDef ( ) ;
OS < < spacing ( ) < < " // " < < prefix < < " _ " < < Subclass - > getName ( ) < < " \n " ;
OS < < spacing ( ) < < " case " < < Subclass - > getName ( ) < < " : \n " ;
addspacing ( ) ;
OS < < spacing ( ) < < " { \n " ;
vi . push_back ( Subclass - > getName ( ) ) ;
// go down hierarchy
InstrSubclasses ( OS , prefix + " _ " + Subclass - > getName ( ) , InstrClassName , SupportedSubclasses , vi , depth + 1 ) ;
// find the record that matches this
Record * theInstructionSet = findInstruction ( OS , InstrClassName , vi ) ;
// only print out the assertion if this is a leaf
if ( ( theInstructionSet = = NULL ) & & ( depth = = ( SupportedSubclasses - > getSize ( ) - 1 ) ) ) {
OS < < spacing ( ) < < " assert(0 && \" No instructions defined for " < < InstrClassName < < " instructions of subclasses " < < prefix < < " _ " < < Subclass - > getName ( ) < < " ! \" ); " < < " \n " ;
} else if ( theInstructionSet ! = NULL ) {
if ( theInstructionSet - > getValueAsString ( " PreCode " ) ! = " " ) {
OS < < spacing ( ) < < theInstructionSet - > getValueAsString ( " PreCode " ) < < " \n \n " ;
}
ListInit * theInstructions = theInstructionSet - > getValueAsListInit ( " Instructions " ) ;
ListInit * registerlists = theInstructionSet - > getValueAsListInit ( " Operands " ) ; // not necessarily registers anymore, but the name will stay for now
for ( unsigned l = 0 , h = theInstructions - > getSize ( ) ; l ! = h ; + + l ) {
DefInit * theInstructionDef = dynamic_cast < DefInit * > ( theInstructions - > getElement ( l ) ) ;
Record * theInstruction = theInstructionDef - > getDef ( ) ;
ListInit * operands = theInstruction - > getValueAsListInit ( " Params " ) ;
OS < < spacing ( ) ;
ListInit * registers = dynamic_cast < ListInit * > ( registerlists - > getElement ( l ) ) ;
// handle virtual instructions here before going to generateBMIcall
if ( theInstruction - > getValueAsString ( " Namespace " ) = = " Virtual " ) {
// create reg for different sizes
std : : string Instr = theInstruction - > getName ( ) ;
StringInit * DestRegInit = dynamic_cast < StringInit * > ( registers - > getElement ( 0 ) ) ;
std : : string DestReg = DestRegInit - > getValue ( ) ;
std : : string theType ;
if ( Instr = = " NullInstruction " ) { } // do nothing
else if ( Instr = = " CreateRegByte " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::SByteTy); \n " ;
else if ( Instr = = " CreateRegShort " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::SShortTy); \n " ;
else if ( Instr = = " CreateRegInt " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::SIntTy); \n " ;
else if ( Instr = = " CreateRegLong " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::SLongTy); \n " ;
else if ( Instr = = " CreateRegUByte " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::UByteTy); \n " ;
else if ( Instr = = " CreateRegUShort " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::UShortTy); \n " ;
else if ( Instr = = " CreateRegUInt " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::UIntTy); \n " ;
else if ( Instr = = " CreateRegULong " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::ULongTy); \n " ;
else if ( Instr = = " CreateRegFloat " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::FloatTy); \n " ;
else if ( Instr = = " CreateRegDouble " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::DoubleTy); \n " ;
else if ( Instr = = " CreateRegPointer " )
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::PointerTy_; \n " ;
else
OS < < " unsigned " < < DestReg < < " = makeAnotherReg(Type::SByteTy); \n " ; // create a byte by default
} else {
std : : string InstrName ;
if ( theInstruction - > getValueAsString ( " Namespace " ) ! = " Virtual " ) {
InstrName = theInstruction - > getValueAsString ( " Namespace " ) + " :: " + theInstruction - > getValueAsString ( " Name " ) ;
} else {
// shouldn't ever happen, virtual instrs should be caught before this
InstrName = theInstruction - > getValueAsString ( " Name " ) ;
}
generateBMIcall ( OS , " *BB " , " IP " , InstrName , theInstruction - > getValueAsInt ( " NumOperands " ) , * operands , * registers ) ;
}
}
if ( theInstructionSet - > getValueAsString ( " PostCode " ) ! = " " ) {
OS < < spacing ( ) < < theInstructionSet - > getValueAsString ( " PostCode " ) < < " \n \n " ;
}
}
if ( InstrSubclassRec - > getValueAsString ( " PostCode " ) ! = " " ) {
//OS << spacing() << "// " << prefix << "_" << Subclass->getName() << "_Prep();\n";
OS < < spacing ( ) < < InstrSubclassRec - > getValueAsString ( " PostCode " ) < < " \n \n " ;
}
OS < < spacing ( ) < < " break; \n " ;
OS < < spacing ( ) < < " } \n \n " ;
remspacing ( ) ;
vi . pop_back ( ) ;
}
// provide a default case for the switch
OS < < spacing ( ) < < " default: \n " ;
OS < < spacing ( ) < < " assert(0 && \" No instructions defined for " < < InstrClassName < < " instructions of subclasses " < < prefix < < " _ " < < SubclassName < < " ! \" ); " < < " \n " ;
OS < < spacing ( ) < < " break; \n \n " ;
remspacing ( ) ;
OS < < spacing ( ) < < " } \n " ;
}
// ret br switch invoke unwind
// add sub mul div rem setcc (eq ne lt gt le ge)
// and or xor sbl sbr
// malloc free alloca load store
// getelementptr phi cast call vanext vaarg
} // End llvm namespace