mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-26 07:34:06 +00:00
Assorted fixes for Win64 EH unwind info emission:
- Flip order of bitfields. This gets our output matching GAS. - Handle case where the end of the prolog wasn't specified. - If the resulting unwind info struct is less than 8 bytes, pad to 8 bytes. Add a test for the latter two. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@132188 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
81e193cc1f
commit
07cbe23173
@ -63,17 +63,17 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
MCWin64EHInstruction &inst) {
|
||||
uint8_t b1, b2;
|
||||
uint16_t w;
|
||||
b2 = (inst.getOperation() & 0x0F) << 4;
|
||||
b2 = (inst.getOperation() & 0x0F);
|
||||
switch (inst.getOperation()) {
|
||||
case Win64EH::UOP_PushNonVol:
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
b2 |= inst.getRegister() & 0x0F;
|
||||
b2 |= (inst.getRegister() & 0x0F) << 4;
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
break;
|
||||
case Win64EH::UOP_AllocLarge:
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
if (inst.getSize() > 512*1024-8) {
|
||||
b2 |= 1;
|
||||
b2 |= 0x10;
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
w = inst.getSize() & 0xFFF8;
|
||||
streamer.EmitIntValue(w, 2);
|
||||
@ -85,7 +85,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
streamer.EmitIntValue(w, 2);
|
||||
break;
|
||||
case Win64EH::UOP_AllocSmall:
|
||||
b2 |= ((inst.getSize()-8) >> 3) & 0x0F;
|
||||
b2 |= (((inst.getSize()-8) >> 3) & 0x0F) << 4;
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
break;
|
||||
@ -96,7 +96,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
break;
|
||||
case Win64EH::UOP_SaveNonVol:
|
||||
case Win64EH::UOP_SaveXMM128:
|
||||
b2 |= inst.getRegister() & 0x0F;
|
||||
b2 |= (inst.getRegister() & 0x0F) << 4;
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
w = inst.getOffset() >> 3;
|
||||
@ -106,7 +106,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
break;
|
||||
case Win64EH::UOP_SaveNonVolBig:
|
||||
case Win64EH::UOP_SaveXMM128Big:
|
||||
b2 |= inst.getRegister() & 0x0F;
|
||||
b2 |= (inst.getRegister() & 0x0F) << 4;
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
if (inst.getOperation() == Win64EH::UOP_SaveXMM128Big)
|
||||
@ -119,7 +119,7 @@ static void EmitUnwindCode(MCStreamer &streamer, MCSymbol *begin,
|
||||
break;
|
||||
case Win64EH::UOP_PushMachFrame:
|
||||
if (inst.isPushCodeFrame())
|
||||
b2 |= 1;
|
||||
b2 |= 0x10;
|
||||
EmitAbsDifference(streamer, inst.getLabel(), begin);
|
||||
streamer.EmitIntValue(b2, 1);
|
||||
break;
|
||||
@ -143,21 +143,24 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
|
||||
MCContext &context = streamer.getContext();
|
||||
streamer.EmitValueToAlignment(4);
|
||||
// Upper 3 bits are the version number (currently 1).
|
||||
uint8_t flags = 0x20;
|
||||
uint8_t flags = 0x01;
|
||||
info->Symbol = context.CreateTempSymbol();
|
||||
streamer.EmitLabel(info->Symbol);
|
||||
|
||||
if (info->ChainedParent)
|
||||
flags |= Win64EH::UNW_ChainInfo;
|
||||
flags |= Win64EH::UNW_ChainInfo << 3;
|
||||
else {
|
||||
if (info->HandlesUnwind)
|
||||
flags |= Win64EH::UNW_TerminateHandler;
|
||||
flags |= Win64EH::UNW_TerminateHandler << 3;
|
||||
if (info->HandlesExceptions)
|
||||
flags |= Win64EH::UNW_ExceptionHandler;
|
||||
flags |= Win64EH::UNW_ExceptionHandler << 3;
|
||||
}
|
||||
streamer.EmitIntValue(flags, 1);
|
||||
|
||||
EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
|
||||
if (info->PrologEnd)
|
||||
EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
|
||||
else
|
||||
streamer.EmitIntValue(0, 1);
|
||||
|
||||
uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
|
||||
streamer.EmitIntValue(numCodes, 1);
|
||||
@ -166,8 +169,8 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
|
||||
if (info->LastFrameInst >= 0) {
|
||||
MCWin64EHInstruction &frameInst = info->Instructions[info->LastFrameInst];
|
||||
assert(frameInst.getOperation() == Win64EH::UOP_SetFPReg);
|
||||
frame = ((frameInst.getRegister() & 0x0F) << 4) |
|
||||
((frameInst.getOffset() >> 4) & 0x0F);
|
||||
frame = (frameInst.getRegister() & 0x0F) |
|
||||
(frameInst.getOffset() & 0xF0);
|
||||
}
|
||||
streamer.EmitIntValue(frame, 1);
|
||||
|
||||
@ -179,11 +182,21 @@ static void EmitUnwindInfo(MCStreamer &streamer, MCWin64EHUnwindInfo *info) {
|
||||
EmitUnwindCode(streamer, info->Begin, inst);
|
||||
}
|
||||
|
||||
if (flags & Win64EH::UNW_ChainInfo)
|
||||
if (flags & (Win64EH::UNW_ChainInfo << 3))
|
||||
EmitRuntimeFunction(streamer, info->ChainedParent);
|
||||
else if (flags &(Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler))
|
||||
else if (flags &
|
||||
((Win64EH::UNW_TerminateHandler|Win64EH::UNW_ExceptionHandler) << 3))
|
||||
streamer.EmitValue(MCSymbolRefExpr::Create(info->ExceptionHandler, context),
|
||||
4);
|
||||
else if (numCodes < 2) {
|
||||
// The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
|
||||
// a chained unwind info, if there is no handler, and if there are fewer
|
||||
// than 2 slots used in the unwind code array, we have to pad to 8 bytes.
|
||||
if (numCodes == 1)
|
||||
streamer.EmitIntValue(0, 2);
|
||||
else
|
||||
streamer.EmitIntValue(0, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void MCWin64EHUnwindEmitter::EmitUnwindInfo(MCStreamer &streamer,
|
||||
|
@ -4,7 +4,7 @@
|
||||
// CHECK: Name = .xdata
|
||||
// CHECK-NEXT: VirtualSize
|
||||
// CHECK-NEXT: VirtualAddress
|
||||
// CHECK-NEXT: SizeOfRawData = 44
|
||||
// CHECK-NEXT: SizeOfRawData = 52
|
||||
// CHECK-NEXT: PointerToRawData
|
||||
// CHECK-NEXT: PointerToRelocations
|
||||
// CHECK-NEXT: PointerToLineNumbers
|
||||
@ -16,9 +16,10 @@
|
||||
// CHECK-NEXT: IMAGE_SCN_MEM_READ
|
||||
// CHECK-NEXT: IMAGE_SCN_MEM_WRITE
|
||||
// CHECK-NEXT: SectionData
|
||||
// CHECK-NEXT: 21 12 08 30 00 30 0F 03 - 0E 88 00 00 09 46 02 00
|
||||
// CHECK-NEXT: 04 22 00 A1 00 00 00 00 - 00 00 00 00 24 00 00 00
|
||||
// CHECK-NEXT: 00 00 00 00 1B 00 00 00 - 00 00 00 00
|
||||
// CHECK-NEXT: 09 12 08 03 00 03 0F 30 - 0E 88 00 00 09 64 02 00
|
||||
// CHECK-NEXT: 04 22 00 1A 00 00 00 00 - 00 00 00 00 21 00 00 00
|
||||
// CHECK-NEXT: 00 00 00 00 1B 00 00 00 - 00 00 00 00 01 00 00 00
|
||||
// CHECK-NEXT: 00 00 00 00
|
||||
|
||||
.text
|
||||
.globl func
|
||||
@ -49,3 +50,11 @@ func:
|
||||
addq $24, %rsp
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
// Test emission of small functions.
|
||||
.globl smallFunc
|
||||
.def smallFunc; .scl 2; .type 32; .endef
|
||||
.seh_proc smallFunc
|
||||
smallFunc:
|
||||
ret
|
||||
.seh_endproc
|
||||
|
Loading…
x
Reference in New Issue
Block a user