Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/backend/ir/debug_info.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
#include "ir/debug_info.h"

namespace rat {
DebugType* DebugInfo::makeType(DebugType::Kind kind, String name, U32 size) {
types.push_back(std::make_unique<DebugType>());
DebugType* t = types.back().get();
t->kind = kind;
t->name = std::move(name);
t->size = size;
return t;
}

// consecutive nodes mostly share a location, reuse the last entry then
U32 DebugBody::addLoc(SrcLoc src) {
const DebugLoc& last = locs.back();
Expand Down
64 changes: 64 additions & 0 deletions src/backend/ir/debug_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,88 @@
#include "core.h"

namespace rat {
struct AllocNode;

struct SrcLoc {
U32 file = 0; // DebugInfo::files
U32 line = 0;
U32 col = 0;
};

struct DebugType {
enum class Kind : U8 {
Signed,
Unsigned,
SignedChar,
UnsignedChar,
Bool,
Float,
ComplexFloat,
Pointer,
Struct,
Union,
Array,
Function,
Typedef,
Enum,
Const,
Volatile
};
struct Member {
String name;
DebugType* type;
U32 offset; // bytes
U32 bitSize = 0; // 0 = not a bitfield
U32 bitOffset = 0;
};

Kind kind;
String name;
U32 size = 0;
DebugType* elem = nullptr; // pointee, element, return, aliased or underlying type, null = void
U64 count = 0; // array length, 0 = unknown
List<Member> members;
List<DebugType*> params;
B32 variadic = false;
B32 incomplete = false; // declared struct without a body
List<Pair<String, I64>> enumerators;
SrcLoc decl; // typedef and enum
};

// a source variable, shared by every copy of its function's code
struct DebugVar {
String name;
DebugType* type;
SrcLoc decl;
String symbol; // static storage, else empty
B32 isParam = false;
};

// a source function, outlives its IR function so inlined copies can still name it
struct DebugFunc {
String name;
SrcLoc decl;
DebugType* ret = nullptr;
B32 external = false;
B32 variadic = false;
List<UniquePtr<DebugVar>> vars; // params first
};

struct DebugLoc {
SrcLoc src;
};

// one copy of a variable in a function's code
struct DebugVarInst {
const DebugVar* var;
AllocNode* slot = nullptr; // frame storage
};

// debug state of one IR function
struct DebugBody {
DebugFunc* func;
List<DebugLoc> locs = List<DebugLoc>(1); // 0 = no location
List<DebugVarInst> vars;

U32 addLoc(SrcLoc src);
};
Expand All @@ -35,7 +95,11 @@ namespace rat {
String producer;
String compDir;
List<String> files; // files[0] is the primary source
List<DebugVar> globals;
List<UniquePtr<DebugFunc>> funcs;
List<UniquePtr<DebugType>> types;

DebugType* makeType(DebugType::Kind kind, String name, U32 size);
};
} // namespace rat

Expand Down
10 changes: 10 additions & 0 deletions src/backend/pass/emit/x86/x86_encode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,15 @@ namespace rat {
encodedFunc->lines.push_back({a->here(), src});
}

void X86EncodePass::recordVars(const Function& f) {
if(!f.getDebug())
return;
for(const DebugVarInst& v : f.getDebug()->vars) {
I32 off = v.slot ? fl->allocOff[v.slot->getId()] : kNoSlot;
encodedFunc->varFrameOff.push_back(off == kNoSlot ? kNoFrameSlot : off - detail::kCfaFromRbp);
}
}

U32 X86EncodePass::blockIdBound(const MachineFunc& f) {
I32 maxId = -1;
for(const MachineBlock& blk : f.blocks)
Expand Down Expand Up @@ -702,6 +711,7 @@ namespace rat {
if(encodedFunc) {
encodedFunc->textOff = off;
encodedFunc->size = (U32)code.size();
recordVars(f);
}
placed.push_back({&f, off, (U32)relocs.size()});
return false;
Expand Down
1 change: 1 addition & 0 deletions src/backend/pass/emit/x86/x86_encode.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ namespace rat {
void prologue();
void markCfi(CfiOp::Kind kind, PhysReg reg, I32 value);
void markLine(U32 loc);
void recordVars(const Function& f);
private:
std::ostream* os;
UniquePtr<ObjectFile> obj;
Expand Down
4 changes: 3 additions & 1 deletion src/backend/pass/emit/x86/x86_lower.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,9 @@ namespace rat {
curLoc = 0;
allocOff.assign(f.idBound(), kNoSlot);
lowerBlocks();
mf.aux = std::make_unique<X86FrameLayout>(frame); // the layout rides along on mf.aux
if(f.getDebug())
frame.allocOff = std::move(allocOff); // slot offsets for variable locations
mf.aux = std::make_unique<X86FrameLayout>(std::move(frame)); // the layout rides along on mf.aux
}

namespace detail {
Expand Down
1 change: 0 additions & 1 deletion src/backend/pass/emit/x86/x86_lower.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,6 @@ namespace rat {
void emitPhiCopies(I32 targetBlock, I32 predIdx);
void emitTerminator(I32 b);
private:
static constexpr I32 kNoSlot = INT32_MIN;
// target
const X86CallConv* conv = &abi::kSysV;
const RegisterInfo* regs = nullptr;
Expand Down
3 changes: 3 additions & 0 deletions src/backend/pass/emit/x86/x86_op.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ namespace rat {
inline Slot slot(I32 s, U32 w = 8) { return {s, w}; }
inline Xmm xmm(U32 n, U32 w = 8) { return {n, w}; }

constexpr I32 kNoSlot = INT32_MIN;

struct X86FrameLayout : MachineFuncAux {
I32 ldScratch = 0;
I32 vecScratch = 0;
Expand All @@ -214,6 +216,7 @@ namespace rat {
U32 namedGp = 0;
U32 namedFp = 0;
I32 sretSlot = 0;
List<I32> allocOff;
};
} // namespace rat

Expand Down
Loading
Loading