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 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
#pragma once
#include "Core/TObject.h"
#include "Core/GcType.h"
#include "Arena.h"
#include "Listing.h"
#include "RefSource.h"
#include "StackFrame.h"
namespace code {
STORM_PKG(core.asm);
/**
* A Binary represents a Listing that has been translated into machine code, along with any
* extra information needed (such as descriptions of exception handlers or similar).
*
* Note: The Binary class expects backends to create a table of data starting at the meta() label
* where each element looks like this:
* size_t freeFn; - a pointer to the function to be executed when this variable is to be freed.
* size_t offset; - a signed offset to the variable relative to the stack frame provided by the backend.
* There shall be one entry for each variable in the Listing. Variable 0 shall be at index 0.
*/
class Binary : public Content {
STORM_CLASS;
public:
// Translate a listing into machine code.
STORM_CTOR Binary(Arena *arena, Listing *src);
// Data structure containing more information about the generated code.
class Info {
STORM_VALUE;
public:
// The created binary.
Binary *binary;
// The transformed listing.
Listing *transformed;
// Offsets of all labels.
Array<Nat> *offsets;
// The variable layout. Not available when 'compileTransformed' is called.
Array<Offset> *varLayout;
// Create.
STORM_CTOR Info(Binary *binary, Listing *transformed, Array<Nat> *offsets, Array<Offset> *layout)
: binary(binary), transformed(transformed), offsets(offsets), varLayout(layout) {}
};
// Create a binary, returning more information than the constructor.
static Info STORM_FN compile(Arena *arena, Listing *src);
// Create a binary, but from a Listing that is already transformed for the current arena.
static Info STORM_FN compileTransformed(Arena *arena, Listing *transformed);
// Clean up a stack frame from this function.
void cleanup(StackFrame &frame);
// Clean up a stack frame from this function from the current block, up to and including
// 'until'. Returns the parent of 'until', which is now to be considered the current part.
Nat cleanup(StackFrame &frame, Nat until);
// Check if we have any catch-clauses at all (used for pre-screening in exception handlers).
inline bool hasCatch() const { return tryBlocks != null; }
// Information on how to resume from a try-clause.
struct Resume {
// Next instruction to execute. 'null' if nothing is to be done.
void *ip;
// Offset from the frame pointer to the stack pointer.
ptrdiff_t stackOffset;
// Part outside the one handling the exception.
size_t cleanUntil;
};
// Check if we have a catch-clause for the active part or any of its parents.
bool hasCatch(Nat part, RootObject *exception, Resume &resume);
// Get the stack offset for this binary, i.e. the difference between the stack pointer and
// the frame pointer for this function (mainly used for cleanup during exceptions).
ptrdiff_t stackOffset() const;
// Get the size of the stack frame. On some platforms, this differs from the stack offset,
// as it depends on where in the stack frame pointer refers to.
size_t stackSize() const;
// Exception status:
inline Bool STORM_FN exceptionCleanup() const { return (flags & ehClean) != 0; }
inline Bool STORM_FN exceptionCaught() const { return (flags & ehCatch) != 0; }
inline Bool STORM_FN exceptionAware() const { return (flags & (ehCatch | ehClean)) != 0; }
// Is this a binary for a member function?
inline Bool STORM_FN isMember() const { return (flags & isMemberFn) != 0; }
// Get result from the function.
MAYBE(TypeDesc *) STORM_FN result() const;
// Get parameters to the function.
Array<TypeDesc *> *STORM_FN params() const;
// Output to string.
virtual void STORM_FN toS(StrBuf *to) const;
// Information about a single variable.
struct Variable {
Nat id;
// The low 16 bits contain FreeOpt, the high 16 bits contain the size of the variable.
Nat flags;
enum {
// Parameter size
sUnknown = 0x0000,
sByte = 0x1000,
sInt = 0x2000,
sLong = 0x3000,
sPtr = 0x4000,
sMask = 0xFF000,
// Mask for freeOpts.
sFreeOptMask = 0xFFF,
// Mask for finding the parameter index (+1).
sParamMask = 0x0FF00000,
sParamShift = 20,
};
// Variable information. Might be null.
Listing::VarInfo *varInfo;
};
// Remember the block hierarchy. These are allocated as GcArray:s to reduce the number of allocations.
struct Block {
// Number of elements.
const size_t count;
// Parent block.
size_t parent;
// Variables in here.
Variable vars[1];
};
// Get access to the block table, intended for 'compatibleSkeleton':
GcArray<Block *> *blockInfo() { return blocks; }
// Get information about variable cleanup.
VarCleanup *cleanupInfo();
// Find a code updater for a specific offset in the code here.
MAYBE(Reference *) STORM_FN findReferenceByOffset(Nat offset);
// Find a code updater for a specific CodeRef slot in the code here.
MAYBE(Reference *) STORM_FN findReferenceBySlot(Nat refSlot);
private:
// For use inside 'compile'.
Binary();
// All blocks.
GcArray<Block *> *blocks;
// Information for try-blocks.
struct TryInfo {
// Current block id.
Nat blockId;
// Offset to continue execution from.
Nat resumeOffset;
// Type to catch.
Type *type;
};
// Try-block information. 'null' if no exceptions are caught. Indices do not correspond to
// parts here since the array is sparse. It is necessary to search the array (perhaps using
// a binary search).
GcArray<TryInfo> *tryBlocks;
// Result and parameter TypeDescs. Element 0 is the result typedesc, remaining is parameters.
GcArray<TypeDesc *> *resultAndParams;
// Offset of the metadata label.
Nat metaOffset;
// Other misc. flags that contains information about the code.
enum {
// Mirrors 'exceptionCleanup' and 'exceptionCaught' in the Listing object.
ehClean = 0x01,
ehCatch = 0x02,
// Is this a member function?
isMemberFn = 0x10,
};
Nat flags;
// Compile the Listing object.
Info compileI(Arena *arena, Listing *src, Bool skipTransform);
// Fill the 'blocks' array.
void fillBlocks(Listing *src);
// Fill the 'tryBlocks' array if necessary.
void fillTryBlocks(Listing *src, LabelOutput *labels);
// Clean a single variable.
void cleanup(StackFrame &frame, Variable &v);
// Fill 'resultAndParams'.
void fillResultAndParams(Listing *src);
// Get the raw value of 'stackOffset'.
ptrdiff_t rawStackOffset() const;
// Type declarations for the GC.
static const GcType blockType;
static const GcType tryInfoArrayType;
};
}
|