blob: f6f6b30f0f2a9de20af7788a37210032b5c6ac25 [file] [log] [blame]
Chris Lattnerbd199fb2002-12-24 00:01:05 +00001//===-- Emitter.cpp - Write machine code to executable memory -------------===//
2//
3// This file defines a MachineCodeEmitter object that is used by Jello to write
4// machine code to memory and remember where relocatable values lie.
5//
6//===----------------------------------------------------------------------===//
7
8#include "VM.h"
9#include "llvm/CodeGen/MachineCodeEmitter.h"
10#include "llvm/CodeGen/MachineFunction.h"
Chris Lattner1cc08382003-01-13 01:00:12 +000011#include "llvm/CodeGen/MachineConstantPool.h"
12#include "llvm/Target/TargetData.h"
Chris Lattnerbd199fb2002-12-24 00:01:05 +000013#include "llvm/Function.h"
14#include "Support/Statistic.h"
15
16namespace {
17 Statistic<> NumBytes("jello", "Number of bytes of machine code compiled");
18
19 class Emitter : public MachineCodeEmitter {
20 VM &TheVM;
21
Chris Lattner6125fdd2003-05-09 03:30:07 +000022 unsigned char *CurBlock, *CurByte;
23
24 // When outputting a function stub in the context of some other function, we
25 // save CurBlock and CurByte here.
26 unsigned char *SavedCurBlock, *SavedCurByte;
Chris Lattnerbd199fb2002-12-24 00:01:05 +000027
28 std::vector<std::pair<BasicBlock*, unsigned *> > BBRefs;
29 std::map<BasicBlock*, unsigned> BBLocations;
Chris Lattner1cc08382003-01-13 01:00:12 +000030 std::vector<void*> ConstantPoolAddresses;
Chris Lattnerbd199fb2002-12-24 00:01:05 +000031 public:
32 Emitter(VM &vm) : TheVM(vm) {}
33
34 virtual void startFunction(MachineFunction &F);
35 virtual void finishFunction(MachineFunction &F);
Chris Lattner1cc08382003-01-13 01:00:12 +000036 virtual void emitConstantPool(MachineConstantPool *MCP);
Chris Lattnerbd199fb2002-12-24 00:01:05 +000037 virtual void startBasicBlock(MachineBasicBlock &BB);
Chris Lattner6125fdd2003-05-09 03:30:07 +000038 virtual void startFunctionStub(const Function &F, unsigned StubSize);
39 virtual void* finishFunctionStub(const Function &F);
Chris Lattnerbd199fb2002-12-24 00:01:05 +000040 virtual void emitByte(unsigned char B);
41 virtual void emitPCRelativeDisp(Value *V);
Chris Lattner1cc08382003-01-13 01:00:12 +000042 virtual void emitGlobalAddress(GlobalValue *V, bool isPCRelative);
43 virtual void emitGlobalAddress(const std::string &Name, bool isPCRelative);
44 virtual void emitFunctionConstantValueAddress(unsigned ConstantNum,
45 int Offset);
46 private:
47 void emitAddress(void *Addr, bool isPCRelative);
Chris Lattnerbd199fb2002-12-24 00:01:05 +000048 };
49}
50
51MachineCodeEmitter *VM::createEmitter(VM &V) {
52 return new Emitter(V);
53}
54
55
56#define _POSIX_MAPPED_FILES
57#include <unistd.h>
58#include <sys/mman.h>
59
Chris Lattner6125fdd2003-05-09 03:30:07 +000060// FIXME: This should be rewritten to support a real memory manager for
61// executable memory pages!
62static void *getMemory(unsigned NumPages) {
63 return mmap(0, 4096*NumPages, PROT_READ|PROT_WRITE|PROT_EXEC,
Chris Lattnerbd199fb2002-12-24 00:01:05 +000064 MAP_PRIVATE|MAP_ANONYMOUS, 0, 0);
65}
66
67
68void Emitter::startFunction(MachineFunction &F) {
Chris Lattner6125fdd2003-05-09 03:30:07 +000069 CurBlock = (unsigned char *)getMemory(8);
Chris Lattnerbd199fb2002-12-24 00:01:05 +000070 CurByte = CurBlock; // Start writing at the beginning of the fn.
71 TheVM.addGlobalMapping(F.getFunction(), CurBlock);
72}
73
74void Emitter::finishFunction(MachineFunction &F) {
Chris Lattner1cc08382003-01-13 01:00:12 +000075 ConstantPoolAddresses.clear();
Chris Lattnerbd199fb2002-12-24 00:01:05 +000076 for (unsigned i = 0, e = BBRefs.size(); i != e; ++i) {
77 unsigned Location = BBLocations[BBRefs[i].first];
78 unsigned *Ref = BBRefs[i].second;
Chris Lattner910687e2003-01-29 18:02:02 +000079 *Ref = Location-(unsigned)(intptr_t)Ref-4;
Chris Lattnerbd199fb2002-12-24 00:01:05 +000080 }
81 BBRefs.clear();
82 BBLocations.clear();
83
84 NumBytes += CurByte-CurBlock;
85
Chris Lattner910687e2003-01-29 18:02:02 +000086 DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex
87 << (unsigned)(intptr_t)CurBlock
Chris Lattnerbd199fb2002-12-24 00:01:05 +000088 << std::dec << "] Function: " << F.getFunction()->getName()
89 << ": " << CurByte-CurBlock << " bytes of text\n");
90}
91
Chris Lattner1cc08382003-01-13 01:00:12 +000092void Emitter::emitConstantPool(MachineConstantPool *MCP) {
93 const std::vector<Constant*> &Constants = MCP->getConstants();
94 for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
95 // For now we just allocate some memory on the heap, this can be
96 // dramatically improved.
97 const Type *Ty = ((Value*)Constants[i])->getType();
98 void *Addr = malloc(TheVM.getTargetData().getTypeSize(Ty));
99 TheVM.InitializeMemory(Constants[i], Addr);
100 ConstantPoolAddresses.push_back(Addr);
101 }
102}
103
104
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000105void Emitter::startBasicBlock(MachineBasicBlock &BB) {
Chris Lattner910687e2003-01-29 18:02:02 +0000106 BBLocations[BB.getBasicBlock()] = (unsigned)(intptr_t)CurByte;
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000107}
108
109
Chris Lattner6125fdd2003-05-09 03:30:07 +0000110void Emitter::startFunctionStub(const Function &F, unsigned StubSize) {
111 SavedCurBlock = CurBlock; SavedCurByte = CurByte;
112 // FIXME: this is a huge waste of memory.
113 CurBlock = (unsigned char *)getMemory((StubSize+4095)/4096);
114 CurByte = CurBlock; // Start writing at the beginning of the fn.
115}
116
117void *Emitter::finishFunctionStub(const Function &F) {
118 NumBytes += CurByte-CurBlock;
119 DEBUG(std::cerr << "Finished CodeGen of [0x" << std::hex
120 << (unsigned)(intptr_t)CurBlock
121 << std::dec << "] Function stub for: " << F.getName()
122 << ": " << CurByte-CurBlock << " bytes of text\n");
123 std::swap(CurBlock, SavedCurBlock);
124 CurByte = SavedCurByte;
125 return SavedCurBlock;
126}
127
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000128void Emitter::emitByte(unsigned char B) {
129 *CurByte++ = B; // Write the byte to memory
130}
131
132
133// emitPCRelativeDisp - For functions, just output a displacement that will
134// cause a reference to the zero page, which will cause a seg-fault, causing
135// things to get resolved on demand. Keep track of these markers.
136//
137// For basic block references, keep track of where the references are so they
138// may be patched up when the basic block is defined.
139//
140void Emitter::emitPCRelativeDisp(Value *V) {
Chris Lattner1cc08382003-01-13 01:00:12 +0000141 BasicBlock *BB = cast<BasicBlock>(V); // Keep track of reference...
142 BBRefs.push_back(std::make_pair(BB, (unsigned*)CurByte));
143 CurByte += 4;
144}
145
146// emitAddress - Emit an address in either direct or PCRelative form...
147//
148void Emitter::emitAddress(void *Addr, bool isPCRelative) {
149 if (isPCRelative) {
Chris Lattner910687e2003-01-29 18:02:02 +0000150 *(intptr_t*)CurByte = (intptr_t)Addr - (intptr_t)CurByte-4;
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000151 } else {
Chris Lattner1cc08382003-01-13 01:00:12 +0000152 *(void**)CurByte = Addr;
153 }
154 CurByte += 4;
155}
156
157void Emitter::emitGlobalAddress(GlobalValue *V, bool isPCRelative) {
158 if (isPCRelative) { // must be a call, this is a major hack!
Chris Lattnereb5a93b2003-05-08 21:44:21 +0000159 // Try looking up the function to see if it is already compiled!
160 if (void *Addr = TheVM.getPointerToGlobalIfAvailable(V)) {
161 emitAddress(Addr, isPCRelative);
162 } else { // Function has not yet been code generated!
163 TheVM.addFunctionRef(CurByte, cast<Function>(V));
Chris Lattnerc309a762003-05-08 21:34:11 +0000164
Chris Lattnereb5a93b2003-05-08 21:44:21 +0000165 // Delayed resolution...
166 emitAddress((void*)VM::CompilationCallback, isPCRelative);
167 }
Chris Lattner1cc08382003-01-13 01:00:12 +0000168 } else {
169 emitAddress(TheVM.getPointerToGlobal(V), isPCRelative);
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000170 }
171}
172
Chris Lattner1cc08382003-01-13 01:00:12 +0000173void Emitter::emitGlobalAddress(const std::string &Name, bool isPCRelative) {
174 emitAddress(TheVM.getPointerToNamedFunction(Name), isPCRelative);
175}
176
177void Emitter::emitFunctionConstantValueAddress(unsigned ConstantNum,
178 int Offset) {
179 assert(ConstantNum < ConstantPoolAddresses.size() &&
180 "Invalid ConstantPoolIndex!");
181 *(void**)CurByte = (char*)ConstantPoolAddresses[ConstantNum]+Offset;
Chris Lattnerbd199fb2002-12-24 00:01:05 +0000182 CurByte += 4;
183}