1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
|
//===-- InstSelectSimple.cpp - A simple instruction selector for x86 ------===//
//
// This file defines a simple peephole instruction selector for the x86 platform
//
//===----------------------------------------------------------------------===//
#include "X86.h"
#include "X86InstructionInfo.h"
#include "llvm/Function.h"
#include "llvm/iTerminators.h"
#include "llvm/Type.h"
#include "llvm/Constants.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/InstVisitor.h"
#include <map>
namespace {
struct ISel : public InstVisitor<ISel> { // eventually will be a FunctionPass
MachineFunction *F; // The function we are compiling into
MachineBasicBlock *BB; // The current MBB we are compiling
unsigned CurReg;
std::map<Value*, unsigned> RegMap; // Mapping between Val's and SSA Regs
ISel(MachineFunction *f)
: F(f), BB(0), CurReg(MRegisterInfo::FirstVirtualRegister) {}
/// runOnFunction - Top level implementation of instruction selection for
/// the entire function.
///
bool runOnFunction(Function &F) {
visit(F);
RegMap.clear();
return false; // We never modify the LLVM itself.
}
/// visitBasicBlock - This method is called when we are visiting a new basic
/// block. This simply creates a new MachineBasicBlock to emit code into
/// and adds it to the current MachineFunction. Subsequent visit* for
/// instructions will be invoked for all instructions in the basic block.
///
void visitBasicBlock(BasicBlock &LLVM_BB) {
BB = new MachineBasicBlock();
// FIXME: Use the auto-insert form when it's available
F->getBasicBlockList().push_back(BB);
}
// Visitation methods for various instructions. These methods simply emit
// fixed X86 code for each instruction.
//
void visitReturnInst(ReturnInst &RI);
void visitAdd(BinaryOperator &B);
void visitInstruction(Instruction &I) {
std::cerr << "Cannot instruction select: " << I;
abort();
}
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
///
void copyConstantToRegister(Constant *C, unsigned Reg);
/// getReg - This method turns an LLVM value into a register number. This
/// is guaranteed to produce the same register number for a particular value
/// every time it is queried.
///
unsigned getReg(Value &V) { return getReg(&V); } // Allow references
unsigned getReg(Value *V) {
unsigned &Reg = RegMap[V];
if (Reg == 0)
Reg = CurReg++;
// If this operand is a constant, emit the code to copy the constant into
// the register here...
//
if (Constant *C = dyn_cast<Constant>(V))
copyConstantToRegister(C, Reg);
return Reg;
}
};
}
/// copyConstantToRegister - Output the instructions required to put the
/// specified constant into the specified register.
///
void ISel::copyConstantToRegister(Constant *C, unsigned R) {
assert (!isa<ConstantExpr>(C) && "Constant expressions not yet handled!\n");
switch (C->getType()->getPrimitiveID()) {
case Type::SByteTyID:
BuildMI(BB, X86::MOVir8, R).addSImm(cast<ConstantSInt>(C)->getValue());
break;
case Type::UByteTyID:
BuildMI(BB, X86::MOVir8, R).addZImm(cast<ConstantUInt>(C)->getValue());
break;
case Type::ShortTyID:
BuildMI(BB, X86::MOVir16, R).addSImm(cast<ConstantSInt>(C)->getValue());
break;
case Type::UShortTyID:
BuildMI(BB, X86::MOVir16, R).addZImm(cast<ConstantUInt>(C)->getValue());
break;
case Type::IntTyID:
BuildMI(BB, X86::MOVir32, R).addSImm(cast<ConstantSInt>(C)->getValue());
break;
case Type::UIntTyID:
BuildMI(BB, X86::MOVir32, R).addZImm(cast<ConstantUInt>(C)->getValue());
break;
default: assert(0 && "Type not handled yet!");
}
}
/// 'ret' instruction - Here we are interested in meeting the x86 ABI. As such,
/// we have the following possibilities:
///
/// ret void: No return value, simply emit a 'ret' instruction
/// ret sbyte, ubyte : Extend value into EAX and return
/// ret short, ushort: Extend value into EAX and return
/// ret int, uint : Move value into EAX and return
/// ret pointer : Move value into EAX and return
/// ret long, ulong : Move value into EAX/EDX (?) and return
/// ret float/double : ? Top of FP stack? XMM0?
///
void ISel::visitReturnInst(ReturnInst &I) {
if (I.getNumOperands() != 0) { // Not 'ret void'?
// Move result into a hard register... then emit a ret
visitInstruction(I); // abort
}
// Emit a simple 'ret' instruction... appending it to the end of the basic
// block
BuildMI(BB, X86::RET, 0);
}
/// 'add' instruction - Simply turn this into an x86 reg,reg add instruction.
void ISel::visitAdd(BinaryOperator &B) {
unsigned Op0r = getReg(B.getOperand(0)), Op1r = getReg(B.getOperand(1));
unsigned DestReg = getReg(B);
switch (B.getType()->getPrimitiveSize()) {
case 1: // UByte, SByte
BuildMI(BB, X86::ADDrr8, DestReg).addReg(Op0r).addReg(Op1r);
break;
case 2: // UShort, Short
BuildMI(BB, X86::ADDrr16, DestReg).addReg(Op0r).addReg(Op1r);
break;
case 4: // UInt, Int
BuildMI(BB, X86::ADDrr32, DestReg).addReg(Op0r).addReg(Op1r);
break;
case 8: // ULong, Long
default:
visitInstruction(B); // abort
}
}
/// 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.
///
MachineFunction *X86SimpleInstructionSelection(Function &F, TargetMachine &TM) {
MachineFunction *Result = new MachineFunction(&F, TM);
ISel(Result).runOnFunction(F);
return Result;
}
|