Browse Source

* throw an error if instructions which needs an operand size is used with one operand being a reference without size

florian 1 year ago
parent
commit
803a6fea24
3 changed files with 50 additions and 1 deletions
  1. 28 0
      compiler/x86/aasmcpu.pas
  2. 12 1
      compiler/x86/rax86.pas
  3. 10 0
      tests/webtbf/tw40399.pp

+ 28 - 0
compiler/x86/aasmcpu.pas

@@ -659,6 +659,8 @@ interface
     function get_ref_address_size(const ref:treference):byte;
     function get_default_segment_of_ref(const ref:treference):tregister;
     procedure optimize_ref(var ref:treference; inlineasm: boolean);
+    { returns true if opcode can be used with one memory operand without size }
+    function NoMemorySizeRequired(opcode : TAsmOp) : Boolean;
 
     function spilling_create_load(const ref:treference;r:tregister):Taicpu;
     function spilling_create_store(r:tregister; const ref:treference):Taicpu;
@@ -5581,6 +5583,32 @@ implementation
       end;
     end;
 
+
+    function NoMemorySizeRequired(opcode : TAsmOp) : Boolean;
+      var
+        i : LongInt;
+        insentry  : PInsEntry;
+      begin
+        result:=false;
+        i:=instabcache^[opcode];
+        if i=-1 then
+         begin
+           Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
+           exit;
+         end;
+        insentry:=@instab[i];
+        while (insentry^.opcode=opcode) do
+         begin
+           if (insentry^.ops=1) and (insentry^.optypes[0]=OT_MEMORY) then
+             begin
+               result:=true;
+               exit;
+             end;
+           inc(insentry);
+         end;
+      end;
+
+
     procedure InitAsm;
       begin
         build_spilling_operation_type_table;

+ 12 - 1
compiler/x86/rax86.pas

@@ -436,10 +436,11 @@ begin
   Opsize:=S_NO;
 end;
 
-procedure Tx86Instruction.AddReferenceSizes;
 { this will add the sizes for references like [esi] which do not
   have the size set yet, it will take only the size if the other
   operand is a register }
+procedure Tx86Instruction.AddReferenceSizes;
+
 var
   operand2,i,j,k : longint;
   s : tasmsymbol;
@@ -1400,6 +1401,16 @@ begin
                    begin
                      if opsize<>S_NO then
                        tx86operand(operands[i]).opsize:=opsize
+                     else if not(NoMemorySizeRequired(opcode) or
+                       (opcode=A_JMP) or (opcode=A_JCC) or (opcode=A_CALL) or (opcode=A_LCALL) or (opcode=A_LJMP)) then
+                       begin
+                         if (m_delphi in current_settings.modeswitches) then
+                           Message(asmr_w_unable_to_determine_reference_size_using_dword)
+                         else
+                           Message(asmr_e_unable_to_determine_reference_size);
+                         { recovery }
+                         tx86operand(operands[i]).opsize:=S_L;
+                       end;
                    end;
                 end;
               OPR_SYMBOL :

+ 10 - 0
tests/webtbf/tw40399.pp

@@ -0,0 +1,10 @@
+{ %cpu=i386 }
+{ %fail }
+{$asmmode intel}
+
+begin
+  asm
+    fnstcw [esi]
+    imul [esi]
+  end;
+end.