FPC 3.1.1 - SEHDirectiveForINTEL.patch (9,217 bytes)
Index: compiler/x86/rax86int.pas
===================================================================
--- compiler/x86/rax86int.pas (revision 31225)
+++ compiler/x86/rax86int.pas (working copy)
@@ -44,7 +44,7 @@
{------------------ Assembler Operators --------------------}
AS_BYTE,AS_WORD,AS_DWORD,AS_QWORD,AS_TBYTE,AS_DQWORD,AS_OWORD,AS_XMMWORD,AS_YWORD,AS_YMMWORD,AS_NEAR,AS_FAR,
AS_HIGH,AS_LOW,AS_OFFSET,AS_SIZEOF,AS_VMTOFFSET,AS_SEG,AS_TYPE,AS_PTR,AS_MOD,AS_SHL,AS_SHR,AS_NOT,
- AS_AND,AS_OR,AS_XOR,AS_WRT,AS___GOTPCREL);
+ AS_AND,AS_OR,AS_XOR,AS_WRT,AS___GOTPCREL, AS_TARGET_DIRECTIVE);
type
tx86intreader = class(tasmreader)
@@ -71,6 +71,9 @@
procedure BuildConstantOperand(oper: tx86operand);
procedure BuildOpCode(instr : tx86instruction);
procedure BuildConstant(constsize: byte);
+
+ function is_targetdirective(const s: string): boolean;virtual;
+ procedure HandleTargetDirective;virtual;
end;
@@ -127,7 +130,7 @@
'','','','','','END',
'','','','','','','','','',
'','','sizeof','vmtoffset','','type','ptr','mod','shl','shr','not',
- 'and','or','xor','wrt','..gotpcrel'
+ 'and','or','xor','wrt','..gotpcrel', 'directive'
);
constructor tx86intreader.create;
@@ -253,6 +256,17 @@
end;
+ function tx86intreader.is_targetdirective(const s: string): boolean;
+ begin
+ result:=false;
+ end;
+
+
+ procedure tx86intreader.handletargetdirective;
+ begin
+ end;
+
+
Procedure tx86intreader.GetToken;
var
len : longint;
@@ -277,6 +291,29 @@
begin
firsttoken:=FALSE;
len:=0;
+
+ { directive check }
+ if c = '.' then
+ Begin
+ actasmpattern:='.';
+ c:=current_scanner.asmgetchar;
+ while c in ['A'..'Z','a'..'z','0'..'9','_'] do
+ begin
+ actasmpattern:=actasmpattern+c;
+ c:=current_scanner.asmgetchar;
+ end;
+ { directives are case sensitive!! }
+ if is_asmdirective(actasmpattern) then
+ exit;
+ if is_targetdirective(actasmpattern) then
+ begin
+ actasmtoken:=AS_TARGET_DIRECTIVE;
+ exit;
+ end;
+ Message1(asmr_e_not_directive_or_local_symbol,actasmpattern);
+ end;
+
+
while c in ['A'..'Z','a'..'z','0'..'9','_','@'] do
begin
{ if there is an at_sign, then this must absolutely be a label }
@@ -608,7 +645,7 @@
end
else
{$endif x86_64}
- actasmtoken:=AS_DOT;
+ actasmtoken:=AS_DOT;
exit;
end;
@@ -2356,6 +2393,9 @@
Consume(AS_SEPARATOR);
end;
+ AS_TARGET_DIRECTIVE:
+ HandleTargetDirective;
+
AS_END :
break; { end assembly block }
Index: compiler/x86_64/rax64int.pas
===================================================================
--- compiler/x86_64/rax64int.pas (revision 31225)
+++ compiler/x86_64/rax64int.pas (working copy)
@@ -26,11 +26,14 @@
interface
uses
- rax86int;
+ rax86int,aasmtai;
type
tx8664intreader = class(tx86intreader)
+ actsehdirective: TAsmSehDirective;
// procedure handleopcode;override;
+ function is_targetdirective(const s:string):boolean;override;
+ procedure HandleTargetDirective;override;
end;
@@ -37,7 +40,7 @@
implementation
uses
- rabase,systems,rax86,aasmcpu;
+ cutils,globtype,rabase,systems,rax86,aasmcpu,cgbase,procinfo,symconst,verbose;
(*
procedure tx8664intreader.handleopcode;
@@ -58,6 +61,154 @@
*)
const
+ { x86_64 subset of SEH directives. .seh_proc and .seh_endproc excluded
+ because they are generated automatically when needed. }
+ recognized_directives: set of TAsmSehDirective=[
+ ash_endprologue,ash_handler,ash_handlerdata,
+ ash_setframe,ash_stackalloc,ash_pushreg,
+ ash_savereg,ash_savexmm,ash_pushframe
+ ];
+
+ { max offset and bitmask for .seh_savereg and .seh_setframe }
+ maxoffset: array[boolean] of aint=(high(dword), 240);
+ modulo: array[boolean] of integer=(7, 15);
+
+ function tx8664intreader.is_targetdirective(const s:string):boolean;
+ var
+ i: TAsmSehDirective;
+ begin
+ result:=false;
+ if target_info.system<>system_x86_64_win64 then exit;
+
+ for i:=low(TAsmSehDirective) to high(TAsmSehDirective) do
+ begin
+ if not (i in recognized_directives) then
+ continue;
+ if s=sehdirectivestr[i] then
+ begin
+ actsehdirective:=i;
+ result:=true;
+ break;
+ end;
+ end;
+ { allow SEH directives only in pure assember routines }
+ if result and not (po_assembler in current_procinfo.procdef.procoptions) then
+ begin
+ Message(asmr_e_seh_in_pure_asm_only);
+ result:=false;
+ end;
+ end;
+
+ procedure tx8664intreader.HandleTargetDirective;
+ var
+ hreg: TRegister;
+ hnum: aint;
+ flags: integer;
+ ai: tai_seh_directive;
+ hs: string;
+ err: boolean;
+ begin
+ if actasmtoken<>AS_TARGET_DIRECTIVE then
+ InternalError(2011100201);
+ Consume(AS_TARGET_DIRECTIVE);
+ Include(current_procinfo.flags,pi_has_unwind_info);
+ case actsehdirective of
+ { TODO: .seh_pushframe is supposed to have a boolean parameter,
+ but GAS 2.21 does not support it. }
+ ash_endprologue,
+ ash_pushframe,
+ ash_handlerdata:
+ curlist.concat(cai_seh_directive.create(actsehdirective));
+ ash_handler:
+ begin
+ hs:=actasmpattern;
+ Consume(AS_ID);
+ flags:=0;
+ err:=false;
+ while actasmtoken=AS_COMMA do
+ begin
+ Consume(AS_COMMA);
+ if actasmtoken=AS_ID then
+ begin
+ uppervar(actasmpattern);
+ if actasmpattern='@EXCEPT' then
+ flags:=flags or 1
+ else if actasmpattern='@UNWIND' then
+ flags:=flags or 2
+ else
+ err:=true;
+ Consume(AS_ID);
+ end
+ else
+ err:=true;
+ if err then
+ begin
+ Message(asmr_e_syntax_error);
+ RecoverConsume(false);
+ exit;
+ end;
+ end;
+
+ ai:=cai_seh_directive.create_name(ash_handler,hs);
+ ai.data.flags:=flags;
+ curlist.concat(ai);
+ end;
+ ash_stackalloc:
+ begin
+ hnum:=BuildConstExpression;//(false,false);
+ if (hnum<0) or (hnum>high(dword)) or ((hnum and 7)<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_stackalloc])
+ else
+ curlist.concat(cai_seh_directive.create_offset(ash_stackalloc,hnum));
+ end;
+ ash_pushreg:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_pushreg])
+ else
+ curlist.concat(cai_seh_directive.create_reg(ash_pushreg,hreg));
+ end;
+ ash_setframe,
+ ash_savereg:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_INTREGISTER) or (getsubreg(hreg)<>R_SUBQ) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[actsehdirective]);
+ Consume(AS_COMMA);
+ hnum:=BuildConstExpression;//(false,false);
+ if (hnum<0) or (hnum>maxoffset[actsehdirective=ash_setframe]) or
+ ((hnum mod modulo[actsehdirective=ash_setframe])<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[actsehdirective])
+ else
+ curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
+ end;
+ ash_savexmm:
+ begin
+ hreg:=actasmregister;
+ Consume(AS_REGISTER);
+ if (getregtype(hreg)<>R_MMREGISTER) then
+ Message1(asmr_e_bad_seh_directive_register,sehdirectivestr[ash_savexmm]);
+ Consume(AS_COMMA);
+ hnum:=BuildConstExpression;//(false,false);
+ if (hnum<0) or (hnum>high(dword)) or ((hnum and 15)<>0) then
+ Message1(asmr_e_bad_seh_directive_offset,sehdirectivestr[ash_savexmm])
+ else
+ curlist.concat(cai_seh_directive.create_reg_offset(actsehdirective,hreg,hnum));
+ end;
+ else
+ InternalError(2011100202);
+ end;
+ if actasmtoken<>AS_SEPARATOR then
+ Consume(AS_SEPARATOR);
+ end;
+
+const
asmmode_x86_64_intel_info : tasmmodeinfo =
(
id : asmmode_x86_64_intel;