diff --git a/compiler/llvm/aasmllvm.pas b/compiler/llvm/aasmllvm.pas index aaf7500073..9c604c3e65 100644 --- a/compiler/llvm/aasmllvm.pas +++ b/compiler/llvm/aasmllvm.pas @@ -200,7 +200,7 @@ implementation uses cutils, strings, symconst, - aasmcpu; + aasmcnst,aasmcpu; { taillvmprocdecl } @@ -553,8 +553,7 @@ uses internalerror(2013110104); end; end; - la_load, - la_getelementptr: + la_load: begin { dst = load ptrdef srcref } case opnr of @@ -564,6 +563,36 @@ uses internalerror(2013110105); end; end; + la_getelementptr: + begin + { dst = getelementptr ref ... } + case opnr of + 0: + begin + case oper[1]^.typ of + top_def: + result:=oper[1]^.def; + top_tai: + begin + case oper[1]^.ai.typ of + ait_llvmins: + result:=taillvm(oper[1]^.ai).spilling_get_reg_type(0); + ait_typedconst: + result:=tai_abstracttypedconst(oper[1]^.ai).def + else + internalerror(2016071202); + end + end + else + internalerror(2016071201); + end + end; + 2: + result:=oper[1]^.def; + else + internalerror(2013110105); + end; + end; la_fence, la_cmpxchg, la_atomicrmw: diff --git a/compiler/llvm/agllvm.pas b/compiler/llvm/agllvm.pas index a71e0b52db..6e6c5647b3 100644 --- a/compiler/llvm/agllvm.pas +++ b/compiler/llvm/agllvm.pas @@ -390,9 +390,11 @@ implementation procedure TLLVMInstrWriter.WriteInstruction(hp: tai); var op: tllvmop; + tmpstr, sep: TSymStr; i, opstart: byte; nested: boolean; + opdone, done: boolean; begin op:=taillvm(hp).llvmopcode; @@ -403,6 +405,7 @@ implementation if owner.fdecllevel=0 then owner.writer.AsmWrite(#9); sep:=' '; + opdone:=false; done:=false; opstart:=0; nested:=false; @@ -414,6 +417,41 @@ implementation owner.writer.AsmWrite(llvmencodetypedecl(taillvm(hp).oper[0]^.def)); done:=true; end; + la_load, + la_getelementptr: + begin + if (taillvm(hp).oper[0]^.typ<>top_reg) or + (taillvm(hp).oper[0]^.reg<>NR_NO) then + owner.writer.AsmWrite(getopstr(taillvm(hp).oper[0]^,false)+' = ') + else + nested:=true; + opstart:=1; + if llvmflag_load_getelptr_type in llvmversion_properties[current_settings.llvmversion] then + begin + owner.writer.AsmWrite(llvm_op2str[op]); + opdone:=true; + if nested then + owner.writer.AsmWrite(' (') + else + owner.writer.AsmWrite(' '); + { can't just dereference the type, because it may be an + implicit pointer type such as a class -> resort to string + manipulation... Not very clean :( } + tmpstr:=llvmencodetypename(taillvm(hp).spilling_get_reg_type(0)); + if op=la_getelementptr then + begin + if tmpstr[length(tmpstr)]<>'*' then + begin + writeln(tmpstr); + internalerror(2016071101); + end + else + setlength(tmpstr,length(tmpstr)-1); + end; + owner.writer.AsmWrite(tmpstr); + owner.writer.AsmWrite(','); + end + end; la_ret, la_br, la_switch, la_indirectbr, la_invoke, la_resume, la_unreachable, @@ -428,8 +466,22 @@ implementation begin if taillvm(hp).oper[1]^.reg<>NR_NO then owner.writer.AsmWrite(getregisterstring(taillvm(hp).oper[1]^.reg)+' = '); - sep:=' '; opstart:=2; + if llvmflag_call_no_ptr in llvmversion_properties[current_settings.llvmversion] then + begin + owner.writer.AsmWrite(llvm_op2str[op]); + opdone:=true; + tmpstr:=llvmencodetypename(taillvm(hp).oper[2]^.def); + if tmpstr[length(tmpstr)]<>'*' then + begin + writeln(tmpstr); + internalerror(2016071102); + end + else + setlength(tmpstr,length(tmpstr)-1); + owner.writer.AsmWrite(tmpstr); + opstart:=3; + end; end; la_blockaddress: begin @@ -495,9 +547,12 @@ implementation { process operands } if not done then begin - owner.writer.AsmWrite(llvm_op2str[op]); - if nested then - owner.writer.AsmWrite(' ('); + if not opdone then + begin + owner.writer.AsmWrite(llvm_op2str[op]); + if nested then + owner.writer.AsmWrite(' ('); + end; if taillvm(hp).ops<>0 then begin for i:=opstart to taillvm(hp).ops-1 do diff --git a/compiler/llvm/llvminfo.pas b/compiler/llvm/llvminfo.pas index fb64645c6f..249fe13fb7 100644 --- a/compiler/llvm/llvminfo.pas +++ b/compiler/llvm/llvminfo.pas @@ -33,6 +33,7 @@ Type llvmver_3_6_0, llvmver_3_6_1, llvmver_3_6_2, + llvmver_3_7_0, { Xcode versions use snapshots of LLVM and don't correspond to released versions of llvm (they don't ship with the llvm utilities either, but they do come with Clang, which can also be used to some extent instead @@ -43,7 +44,9 @@ Type type tllvmversionflag = ( llvmflag_metadata_keyword, { use "metadata" keyword (others leave it away, except when metadata is an argument to call instructions) } - llvmflag_linker_private { have linker_private linkage type (later versions use global in combination with hidden visibility) } + llvmflag_linker_private, { have linker_private linkage type (later versions use global in combination with hidden visibility) } + llvmflag_load_getelptr_type, { the return type of loads and the base type of getelementptr must be specified } + llvmflag_call_no_ptr { with direct calls, the function type is not a function pointer } ); tllvmversionflags = set of tllvmversionflag; @@ -59,7 +62,8 @@ Const 'LLVM-3.6.0', 'LLVM-3.6.1', 'LLVM-3.6.2', - 'LLVM-Xcode-6.4' + 'LLVM-3.7.0', + 'LLVM-Xcode-6.4' { somewhere around LLVM 3.6.0 } ); llvmversion_properties: array[tllvmversion] of tllvmversionflags = @@ -74,6 +78,7 @@ Const { llvmver_3_6_0 } [], { llvmver_3_6_1 } [], { llvmver_3_6_2 } [], + { llvmver_3_7_0 } [llvmflag_load_getelptr_type,llvmflag_call_no_ptr], { llvmver_xc_6_4 } [llvmflag_metadata_keyword] );