diff --git a/compiler/llvm/agllvm.pas b/compiler/llvm/agllvm.pas index a8833ef6bc..8e8ff5a134 100644 --- a/compiler/llvm/agllvm.pas +++ b/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:=''; diff --git a/compiler/llvm/nllvmbas.pas b/compiler/llvm/nllvmbas.pas index e298c28ea7..4cbd8a4b42 100644 --- a/compiler/llvm/nllvmbas.pas +++ b/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;