Browse Source

* escape all occurrences of '$' in function-level inline assembly
o temporarily encode the uses of '$' for references to function-level inline
assembly arguments as '^', because those have to remain/become a single
'$'

git-svn-id: trunk@34898 -

Jonas Maebe 8 years ago
parent
commit
e1e3ad15f0
2 changed files with 40 additions and 13 deletions
  1. 35 12
      compiler/llvm/agllvm.pas
  2. 5 1
      compiler/llvm/nllvmbas.pas

+ 35 - 12
compiler/llvm/agllvm.pas

@@ -33,17 +33,15 @@ interface
     type
       TLLVMInstrWriter = class;
 
-      TLLVMBaseInlineAssemblyDecorator = class
-        function LineFilter(const s: AnsiString): AnsiString;
-      end;
-
-      TLLVMModuleInlineAssemblyDecorator = class(TLLVMBaseInlineAssemblyDecorator,IExternalAssemblerOutputFileDecorator)
+      TLLVMModuleInlineAssemblyDecorator = class(IExternalAssemblerOutputFileDecorator)
+       function LineFilter(const s: AnsiString): AnsiString;
        function LinePrefix: AnsiString;
        function LinePostfix: AnsiString;
        function LineEnding(const deflineending: ShortString): ShortString;
       end;
 
-      TLLVMFunctionInlineAssemblyDecorator = class(TLLVMBaseInlineAssemblyDecorator,IExternalAssemblerOutputFileDecorator)
+      TLLVMFunctionInlineAssemblyDecorator = class(IExternalAssemblerOutputFileDecorator)
+       function LineFilter(const s: AnsiString): AnsiString;
        function LinePrefix: AnsiString;
        function LinePostfix: AnsiString;
        function LineEnding(const deflineending: ShortString): ShortString;
@@ -151,10 +149,10 @@ implementation
       end;
 
 {****************************************************************************}
-{            Common decorator functionality for inline assembly              }
+{               Decorator for module-level inline assembly                   }
 {****************************************************************************}
 
-    function TLLVMBaseInlineAssemblyDecorator.LineFilter(const s: AnsiString): AnsiString;
+    function TLLVMModuleInlineAssemblyDecorator.LineFilter(const s: AnsiString): AnsiString;
       var
         i: longint;
       begin
@@ -176,10 +174,6 @@ implementation
         end;
 
 
-{****************************************************************************}
-{               Decorator for module-level inline assembly                   }
-{****************************************************************************}
-
     function TLLVMModuleInlineAssemblyDecorator.LinePrefix: AnsiString;
       begin
         result:='module asm "';
@@ -203,6 +197,35 @@ implementation
 {****************************************************************************}
 
 
+    function TLLVMFunctionInlineAssemblyDecorator.LineFilter(const s: AnsiString): AnsiString;
+      var
+        i: longint;
+      begin
+        result:='';
+        for i:=1 to length(s) do
+          begin
+            case s[i] of
+              { escape dollars }
+              '$':
+                 result:=result+'$$';
+              { ^ is used as placeholder for a single dollar (reference to
+                 argument to the inline assembly) }
+              '^':
+                 result:=result+'$';
+              #0..#31,
+              #127..#255,
+              '"','\':
+                result:=result+
+                        '\'+
+                        chr((ord(s[i]) shr 4)+ord('0'))+
+                        chr((ord(s[i]) and $f)+ord('0'));
+            else
+              result:=result+s[i];
+            end;
+          end;
+        end;
+
+
     function TLLVMFunctionInlineAssemblyDecorator.LinePrefix: AnsiString;
       begin
         result:='';

+ 5 - 1
compiler/llvm/nllvmbas.pas

@@ -109,7 +109,11 @@ interface
 
     function tllvmasmnode.getllvmasmparasym(sym: tabstractnormalvarsym): tasmsymbol;
       begin
-        result:=current_asmdata.RefAsmSymbol('$'+tostr(getllvmasmopindexforsym(sym)),AT_DATA,false);
+        { these have to be transformed from ^nr into into $nr; we use ^ because
+          we also have to double all other occurrences of '$' in the assembly
+          code, and we can't differentiate between these and other '$'s in
+          agllvm }
+        result:=current_asmdata.RefAsmSymbol('^'+tostr(getllvmasmopindexforsym(sym)),AT_DATA,false);
       end;