View Issue Details

IDProjectCategoryView StatusLast Update
0029894FPCCompilerpublic2020-08-07 02:08
ReporterEmelyanov Roman Assigned ToFlorian  
PrioritynormalSeverityminorReproducibilityN/A
Status resolvedResolutionfixed 
Platformx86_64OSWindows 
Product Version3.1.1 
Fixed in Version3.1.1 
Summary0029894: Patch to add support of SEH directive in FPC internal assembler with INTEL syntax.
DescriptionI make small patch to add support of SEH directive FPC internal assembler with INTEL syntax. Please check it and if its ok - include to trunk.
TagsNo tags attached.
Fixed in Revision38331
FPCOldBugId
FPCTarget
Attached Files

Relationships

related to 0032792 resolvedFlorian [Feature Request] A means to configure stack unwinding under Intel-syntax assembler 

Activities

Emelyanov Roman

2016-03-25 00:46

reporter  

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;

Florian

2018-02-24 17:14

administrator   ~0106576

Thanks, applied.

Issue History

Date Modified Username Field Change
2016-03-25 00:46 Emelyanov Roman New Issue
2016-03-25 00:46 Emelyanov Roman File Added: FPC 3.1.1 - SEHDirectiveForINTEL.patch
2018-02-24 15:54 Florian Relationship added related to 0032792
2018-02-24 17:14 Florian Fixed in Revision => 38331
2018-02-24 17:14 Florian Note Added: 0106576
2018-02-24 17:14 Florian Status new => resolved
2018-02-24 17:14 Florian Fixed in Version => 3.1.1
2018-02-24 17:14 Florian Resolution open => fixed
2018-02-24 17:14 Florian Assigned To => Florian