mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-06-06 09:38:23 +02:00
* synchronized with trunk
git-svn-id: branches/wasm@46466 -
This commit is contained in:
commit
78ad7b7dfa
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -16596,6 +16596,7 @@ tests/webtbf/tw3740.pp svneol=native#text/plain
|
|||||||
tests/webtbf/tw37460.pp svneol=native#text/pascal
|
tests/webtbf/tw37460.pp svneol=native#text/pascal
|
||||||
tests/webtbf/tw37462.pp svneol=native#text/pascal
|
tests/webtbf/tw37462.pp svneol=native#text/pascal
|
||||||
tests/webtbf/tw37475.pp svneol=native#text/pascal
|
tests/webtbf/tw37475.pp svneol=native#text/pascal
|
||||||
|
tests/webtbf/tw37476.pp svneol=native#text/pascal
|
||||||
tests/webtbf/tw3790.pp svneol=native#text/plain
|
tests/webtbf/tw3790.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3812.pp svneol=native#text/plain
|
tests/webtbf/tw3812.pp svneol=native#text/plain
|
||||||
tests/webtbf/tw3930a.pp svneol=native#text/plain
|
tests/webtbf/tw3930a.pp svneol=native#text/plain
|
||||||
|
@ -50,6 +50,7 @@ Interface
|
|||||||
function RemoveSuperfluousFMov(const p: tai; movp: tai; const optimizer: string): boolean;
|
function RemoveSuperfluousFMov(const p: tai; movp: tai; const optimizer: string): boolean;
|
||||||
function OptPass1STP(var p: tai): boolean;
|
function OptPass1STP(var p: tai): boolean;
|
||||||
function OptPass1Mov(var p: tai): boolean;
|
function OptPass1Mov(var p: tai): boolean;
|
||||||
|
function OptPass1FMov(var p: tai): Boolean;
|
||||||
End;
|
End;
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
@ -60,6 +61,16 @@ Implementation
|
|||||||
cgutils,
|
cgutils,
|
||||||
verbose;
|
verbose;
|
||||||
|
|
||||||
|
{$ifdef DEBUG_AOPTCPU}
|
||||||
|
const
|
||||||
|
SPeepholeOptimization: shortstring = 'Peephole Optimization: ';
|
||||||
|
{$else DEBUG_AOPTCPU}
|
||||||
|
{ Empty strings help the optimizer to remove string concatenations that won't
|
||||||
|
ever appear to the user on release builds. [Kit] }
|
||||||
|
const
|
||||||
|
SPeepholeOptimization = '';
|
||||||
|
{$endif DEBUG_AOPTCPU}
|
||||||
|
|
||||||
function CanBeCond(p : tai) : boolean;
|
function CanBeCond(p : tai) : boolean;
|
||||||
begin
|
begin
|
||||||
result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
|
result:=(p.typ=ait_instruction) and (taicpu(p).condition=C_None);
|
||||||
@ -490,6 +501,31 @@ Implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.OptPass1FMov(var p: tai): Boolean;
|
||||||
|
var
|
||||||
|
hp1: tai;
|
||||||
|
begin
|
||||||
|
{
|
||||||
|
change
|
||||||
|
fmov reg0,reg1
|
||||||
|
fmov reg1,reg0
|
||||||
|
into
|
||||||
|
fmov reg0,reg1
|
||||||
|
}
|
||||||
|
Result := False;
|
||||||
|
while GetNextInstruction(p, hp1) and
|
||||||
|
MatchInstruction(hp1, A_FMOV, [taicpu(p).condition], [taicpu(p).oppostfix]) and
|
||||||
|
MatchOperand(taicpu(p).oper[0]^, taicpu(hp1).oper[1]^) and
|
||||||
|
MatchOperand(taicpu(p).oper[1]^, taicpu(hp1).oper[0]^) do
|
||||||
|
begin
|
||||||
|
asml.Remove(hp1);
|
||||||
|
hp1.free;
|
||||||
|
DebugMsg(SPeepholeOptimization + 'FMovFMov2FMov done', p);
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function TCpuAsmOptimizer.OptPostCMP(var p : tai): boolean;
|
function TCpuAsmOptimizer.OptPostCMP(var p : tai): boolean;
|
||||||
var
|
var
|
||||||
hp1,hp2: tai;
|
hp1,hp2: tai;
|
||||||
@ -580,7 +616,9 @@ Implementation
|
|||||||
if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
RemoveSuperfluousFMov(p, hp1, 'FOpFMov2FOp') then
|
RemoveSuperfluousFMov(p, hp1, 'FOpFMov2FOp') then
|
||||||
Result:=true;
|
Result:=true;
|
||||||
end
|
end;
|
||||||
|
A_FMOV:
|
||||||
|
Result:=OptPass1FMov(p);
|
||||||
else
|
else
|
||||||
;
|
;
|
||||||
end;
|
end;
|
||||||
|
@ -882,7 +882,7 @@ Implementation
|
|||||||
if (target_ar.id in [ar_gnu_ar_scripted,ar_sdcc_sdar_scripted]) then
|
if (target_ar.id in [ar_gnu_ar_scripted,ar_sdcc_sdar_scripted]) then
|
||||||
writeln(script, 'CREATE ' + current_module.staticlibfilename)
|
writeln(script, 'CREATE ' + current_module.staticlibfilename)
|
||||||
else { wlib case }
|
else { wlib case }
|
||||||
writeln(script,'-q -fo -c -b '+
|
writeln(script,'-q -p=16 -fo -c -b '+
|
||||||
maybequoted(current_module.staticlibfilename));
|
maybequoted(current_module.staticlibfilename));
|
||||||
current := TCmdStrListItem(SmartLinkOFiles.First);
|
current := TCmdStrListItem(SmartLinkOFiles.First);
|
||||||
while current <> nil do
|
while current <> nil do
|
||||||
@ -1743,8 +1743,8 @@ Implementation
|
|||||||
ar_watcom_wlib_omf_info : tarinfo =
|
ar_watcom_wlib_omf_info : tarinfo =
|
||||||
( id : ar_watcom_wlib_omf;
|
( id : ar_watcom_wlib_omf;
|
||||||
addfilecmd : '+';
|
addfilecmd : '+';
|
||||||
arfirstcmd : 'wlib -q -fo -c -b -n -o=$OUTPUTLIB $LIB $FILES';
|
arfirstcmd : 'wlib -q -p=16 -fo -c -b -n -o=$OUTPUTLIB $LIB $FILES';
|
||||||
arcmd : 'wlib -q -fo -c -b -o=$OUTPUTLIB $LIB $FILES';
|
arcmd : 'wlib -q -p=16 -fo -c -b -o=$OUTPUTLIB $LIB $FILES';
|
||||||
arfinishcmd : ''
|
arfinishcmd : ''
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1326,7 +1326,9 @@ implementation
|
|||||||
(right.nodetype in [ltn,lten,gtn,gten]) and
|
(right.nodetype in [ltn,lten,gtn,gten]) and
|
||||||
(not might_have_sideeffects(left)) and
|
(not might_have_sideeffects(left)) and
|
||||||
(not might_have_sideeffects(right)) and
|
(not might_have_sideeffects(right)) and
|
||||||
is_range_test(taddnode(left),taddnode(right),vl,cl,cr) then
|
is_range_test(taddnode(left),taddnode(right),vl,cl,cr) and
|
||||||
|
{ avoid optimization being applied to (<string. var > charconst1) and (<string. var < charconst2) }
|
||||||
|
(vl.resultdef.typ in [orddef,enumdef]) then
|
||||||
begin
|
begin
|
||||||
hdef:=get_unsigned_inttype(vl.resultdef);
|
hdef:=get_unsigned_inttype(vl.resultdef);
|
||||||
vl:=ctypeconvnode.create_internal(vl.getcopy,hdef);
|
vl:=ctypeconvnode.create_internal(vl.getcopy,hdef);
|
||||||
@ -3000,7 +3002,7 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if not codegenerror and
|
if (errorcount=0) and
|
||||||
not assigned(result) then
|
not assigned(result) then
|
||||||
result:=simplify(false);
|
result:=simplify(false);
|
||||||
end;
|
end;
|
||||||
|
@ -623,6 +623,18 @@ implementation
|
|||||||
assigned(funcretnode) then
|
assigned(funcretnode) then
|
||||||
hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,realresdef,retloc,location,false);
|
hlcg.gen_load_cgpara_loc(current_asmdata.CurrAsmList,realresdef,retloc,location,false);
|
||||||
|
|
||||||
|
if ((location.loc=LOC_REGISTER) and
|
||||||
|
not realresdef.is_intregable) or
|
||||||
|
((location.loc in [LOC_FPUREGISTER,LOC_MMREGISTER]) and
|
||||||
|
(not realresdef.is_fpuregable or
|
||||||
|
((location.loc=LOC_MMREGISTER)<>use_vectorfpu(realresdef)))) then
|
||||||
|
begin
|
||||||
|
hlcg.location_force_mem(current_asmdata.CurrAsmList,location,realresdef);
|
||||||
|
{ may have been record returned in a floating point register (-> location.size
|
||||||
|
will be the size of the fpuregister instead of the int size of the record) }
|
||||||
|
location.size:=def_cgsize(realresdef);
|
||||||
|
end;
|
||||||
|
|
||||||
{ copy value to the final location if this was already provided to the
|
{ copy value to the final location if this was already provided to the
|
||||||
callnode. This must be done after the call node, because the location can
|
callnode. This must be done after the call node, because the location can
|
||||||
also be used as parameter and may not be finalized yet }
|
also be used as parameter and may not be finalized yet }
|
||||||
|
@ -623,7 +623,7 @@ implementation
|
|||||||
begin
|
begin
|
||||||
sym:=tsym(fields[i]);
|
sym:=tsym(fields[i]);
|
||||||
write_rtti_reference(tcb,tfieldvarsym(sym).vardef,rt);
|
write_rtti_reference(tcb,tfieldvarsym(sym).vardef,rt);
|
||||||
tcb.emit_ord_const(tfieldvarsym(sym).fieldoffset,ptruinttype);
|
tcb.emit_ord_const(tfieldvarsym(sym).fieldoffset,sizeuinttype);
|
||||||
end;
|
end;
|
||||||
fields.free;
|
fields.free;
|
||||||
end;
|
end;
|
||||||
|
@ -3178,9 +3178,14 @@ const
|
|||||||
result:=target_info.Cprefix+tprocdef(pd).procsym.realname
|
result:=target_info.Cprefix+tprocdef(pd).procsym.realname
|
||||||
else
|
else
|
||||||
result:=pd.procsym.realname;
|
result:=pd.procsym.realname;
|
||||||
|
{$ifdef i8086}
|
||||||
|
{ Turbo Pascal expects names of external routines
|
||||||
|
to be all uppercase }
|
||||||
if (target_info.system=system_i8086_msdos) and
|
if (target_info.system=system_i8086_msdos) and
|
||||||
|
(m_tp7 in current_settings.modeswitches) and
|
||||||
(pd.proccalloption=pocall_pascal) then
|
(pd.proccalloption=pocall_pascal) then
|
||||||
result:=UpCase(result);
|
result:=UpCase(result);
|
||||||
|
{$endif i8086}
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
@ -460,6 +460,16 @@ implementation
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef i8086}
|
||||||
|
{ enable cs_force_far_calls when m_nested_procvars is enabled }
|
||||||
|
if switch=m_nested_procvars then
|
||||||
|
begin
|
||||||
|
include(current_settings.localswitches,cs_force_far_calls);
|
||||||
|
if changeinit then
|
||||||
|
include(init_settings.localswitches,cs_force_far_calls);
|
||||||
|
end;
|
||||||
|
{$endif i8086}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -605,12 +615,18 @@ implementation
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
{$ifdef i8086}
|
{$ifdef i8086}
|
||||||
{ Do not force far calls in the TP mode by default }
|
{ Do not force far calls in the TP mode by default, force it in other modes }
|
||||||
if (m_tp7 in current_settings.modeswitches) then
|
if (m_tp7 in current_settings.modeswitches) then
|
||||||
begin
|
begin
|
||||||
exclude(current_settings.localswitches,cs_force_far_calls);
|
exclude(current_settings.localswitches,cs_force_far_calls);
|
||||||
if changeinit then
|
if changeinit then
|
||||||
exclude(init_settings.localswitches,cs_force_far_calls);
|
exclude(init_settings.localswitches,cs_force_far_calls);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
include(current_settings.localswitches,cs_force_far_calls);
|
||||||
|
if changeinit then
|
||||||
|
include(init_settings.localswitches,cs_force_far_calls);
|
||||||
end;
|
end;
|
||||||
{$endif i8086}
|
{$endif i8086}
|
||||||
|
|
||||||
|
@ -100,8 +100,8 @@ interface
|
|||||||
tarinfo = record
|
tarinfo = record
|
||||||
id : tar;
|
id : tar;
|
||||||
addfilecmd : string[10];
|
addfilecmd : string[10];
|
||||||
arfirstcmd : string[50];
|
arfirstcmd : string[60];
|
||||||
arcmd : string[50];
|
arcmd : string[60];
|
||||||
arfinishcmd : string[11];
|
arfinishcmd : string[11];
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1788,14 +1788,16 @@ unit aoptx86;
|
|||||||
InternalError(2020072501);
|
InternalError(2020072501);
|
||||||
|
|
||||||
{ do not mess with the stack point as adjusting it by lea is recommend, except if we optimize for size }
|
{ do not mess with the stack point as adjusting it by lea is recommend, except if we optimize for size }
|
||||||
if (taicpu(p).oper[1]^.reg=NR_STACK_POINTER_REG) and
|
if (p.oper[1]^.reg=NR_STACK_POINTER_REG) and
|
||||||
not(cs_opt_size in current_settings.optimizerswitches) then
|
not(cs_opt_size in current_settings.optimizerswitches) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
with p.oper[0]^.ref^ do
|
with p.oper[0]^.ref^ do
|
||||||
begin
|
begin
|
||||||
if (base <> p.oper[1]^.reg) or (index <> NR_NO) then
|
if (base <> p.oper[1]^.reg) or
|
||||||
Exit(False);
|
(index <> NR_NO) or
|
||||||
|
assigned(symbol) then
|
||||||
|
exit;
|
||||||
|
|
||||||
l:=offset;
|
l:=offset;
|
||||||
if (l=1) and UseIncDec then
|
if (l=1) and UseIncDec then
|
||||||
|
@ -43,6 +43,8 @@ Interface
|
|||||||
function InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;override;
|
function InstructionLoadsFromReg(const reg: TRegister; const hp: tai): boolean;override;
|
||||||
function GetNextInstructionUsingReg(Current : tai; out Next : tai; reg : TRegister) : Boolean;
|
function GetNextInstructionUsingReg(Current : tai; out Next : tai; reg : TRegister) : Boolean;
|
||||||
procedure DebugMsg(const s : string; p : tai);
|
procedure DebugMsg(const s : string; p : tai);
|
||||||
|
|
||||||
|
function PeepHoleOptPass1Cpu(var p: tai): boolean; override;
|
||||||
private
|
private
|
||||||
function RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string): boolean;
|
function RemoveSuperfluousMove(const p: tai; movp: tai; const optimizer: string): boolean;
|
||||||
End;
|
End;
|
||||||
@ -145,6 +147,24 @@ Implementation
|
|||||||
Result := false;
|
Result := false;
|
||||||
if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
|
if not ((assigned(hp)) and (hp.typ = ait_instruction)) then
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
|
if Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
case p.opcode of
|
||||||
|
A_B,
|
||||||
|
A_SSI,A_SSIU,A_SSX,A_SSXU,
|
||||||
|
A_S16I,A_S32C1I,A_S32E,A_S32I,A_S32RI,A_S8I:
|
||||||
|
exit;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
|
case p.oper[0]^.typ of
|
||||||
|
top_reg:
|
||||||
|
Result := (p.oper[0]^.reg = reg) ;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -192,7 +212,6 @@ Implementation
|
|||||||
begin
|
begin
|
||||||
Result:=false;
|
Result:=false;
|
||||||
if MatchInstruction(movp, A_MOV, [PF_None,PF_N]) and
|
if MatchInstruction(movp, A_MOV, [PF_None,PF_N]) and
|
||||||
(taicpu(p).ops>=3) and
|
|
||||||
{ We can't optimize if there is a shiftop }
|
{ We can't optimize if there is a shiftop }
|
||||||
(taicpu(movp).ops=2) and
|
(taicpu(movp).ops=2) and
|
||||||
MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
|
MatchOperand(taicpu(movp).oper[1]^, taicpu(p).oper[0]^.reg) and
|
||||||
@ -200,10 +219,10 @@ Implementation
|
|||||||
not(RegUsedBetween(taicpu(movp).oper[0]^.reg,p,movp)) and
|
not(RegUsedBetween(taicpu(movp).oper[0]^.reg,p,movp)) and
|
||||||
{ Take care to only do this for instructions which REALLY load to the first register.
|
{ Take care to only do this for instructions which REALLY load to the first register.
|
||||||
Otherwise
|
Otherwise
|
||||||
str reg0, [reg1]
|
s* reg0, [reg1]
|
||||||
mov reg2, reg0
|
mov reg2, reg0
|
||||||
will be optimized to
|
will be optimized to
|
||||||
str reg2, [reg1]
|
s* reg2, [reg1]
|
||||||
}
|
}
|
||||||
RegLoadedWithNewValue(taicpu(p).oper[0]^.reg, p) then
|
RegLoadedWithNewValue(taicpu(p).oper[0]^.reg, p) then
|
||||||
begin
|
begin
|
||||||
@ -239,25 +258,38 @@ Implementation
|
|||||||
|
|
||||||
{ finally get rid of the mov }
|
{ finally get rid of the mov }
|
||||||
taicpu(p).loadreg(0,taicpu(movp).oper[0]^.reg);
|
taicpu(p).loadreg(0,taicpu(movp).oper[0]^.reg);
|
||||||
{ Remove preindexing and postindexing for LDR in some cases.
|
|
||||||
For example:
|
|
||||||
ldr reg2,[reg1, xxx]!
|
|
||||||
mov reg1,reg2
|
|
||||||
must be translated to:
|
|
||||||
ldr reg1,[reg1, xxx]
|
|
||||||
|
|
||||||
Preindexing must be removed there, since the same register is used as the base and as the target.
|
|
||||||
Such case is not allowed for ARM CPU and produces crash. }
|
|
||||||
//if (taicpu(p).opcode = A_LDR) and (taicpu(p).oper[1]^.typ = top_ref)
|
|
||||||
// and (taicpu(movp).oper[0]^.reg = taicpu(p).oper[1]^.ref^.base)
|
|
||||||
//then
|
|
||||||
// taicpu(p).oper[1]^.ref^.addressmode:=AM_OFFSET;
|
|
||||||
asml.remove(movp);
|
asml.remove(movp);
|
||||||
movp.free;
|
movp.free;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
function TCpuAsmOptimizer.PeepHoleOptPass1Cpu(var p: tai): boolean;
|
||||||
|
var
|
||||||
|
hp1: tai;
|
||||||
|
begin
|
||||||
|
result := false;
|
||||||
|
case p.typ of
|
||||||
|
ait_instruction:
|
||||||
|
begin
|
||||||
|
case taicpu(p).opcode of
|
||||||
|
A_L32I:
|
||||||
|
begin
|
||||||
|
if GetNextInstructionUsingReg(p, hp1, taicpu(p).oper[0]^.reg) and
|
||||||
|
RemoveSuperfluousMove(p, hp1, 'L32IMov2L32I') then
|
||||||
|
Result:=true;
|
||||||
|
end;
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
;
|
||||||
|
end
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
casmoptimizer:=TCpuAsmOptimizer;
|
casmoptimizer:=TCpuAsmOptimizer;
|
||||||
End.
|
End.
|
||||||
|
@ -2880,7 +2880,10 @@ begin
|
|||||||
Result:=TSQLAsteriskExpression(CreateElement(TSQLAsteriskExpression,APArent));
|
Result:=TSQLAsteriskExpression(CreateElement(TSQLAsteriskExpression,APArent));
|
||||||
GetNextToken;
|
GetNextToken;
|
||||||
end;
|
end;
|
||||||
tsqlIdentifier:
|
else
|
||||||
|
// some keywords (FirstKeyword..LastKeyWord) can also be functions/identifiers (LEFT, RIGHT)
|
||||||
|
// To-Do: remove some of them if necessary
|
||||||
|
if CurrentToken in [tsqlIdentifier, FirstKeyword..LastKeyWord] then
|
||||||
begin
|
begin
|
||||||
N:=CurrentTokenString;
|
N:=CurrentTokenString;
|
||||||
If (GetNextToken<>tsqlBraceOpen) then
|
If (GetNextToken<>tsqlBraceOpen) then
|
||||||
@ -2941,10 +2944,10 @@ begin
|
|||||||
TSQLFunctionCallExpression(Result).IDentifier:=N;
|
TSQLFunctionCallExpression(Result).IDentifier:=N;
|
||||||
TSQLFunctionCallExpression(Result).Arguments:=L;
|
TSQLFunctionCallExpression(Result).Arguments:=L;
|
||||||
end;
|
end;
|
||||||
end;
|
end
|
||||||
else
|
else
|
||||||
UnexpectedToken;
|
UnexpectedToken;
|
||||||
end;
|
end;
|
||||||
except
|
except
|
||||||
FreeAndNil(Result);
|
FreeAndNil(Result);
|
||||||
Raise;
|
Raise;
|
||||||
|
@ -450,6 +450,7 @@ type
|
|||||||
procedure TestAggregateAvgDistinct;
|
procedure TestAggregateAvgDistinct;
|
||||||
procedure TestUpperConst;
|
procedure TestUpperConst;
|
||||||
procedure TestUpperError;
|
procedure TestUpperError;
|
||||||
|
procedure TestLeft;
|
||||||
procedure TestGenID;
|
procedure TestGenID;
|
||||||
procedure TestGenIDError1;
|
procedure TestGenIDError1;
|
||||||
procedure TestGenIDError2;
|
procedure TestGenIDError2;
|
||||||
@ -4778,6 +4779,31 @@ begin
|
|||||||
AssertAggregateExpression(H.Left,afCount,'C',aoNone);
|
AssertAggregateExpression(H.Left,afCount,'C',aoNone);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TTestSelectParser.TestLeft;
|
||||||
|
|
||||||
|
Var
|
||||||
|
E : TSQLFunctionCallExpression;
|
||||||
|
L : TSQLLiteralExpression;
|
||||||
|
S : TSQLStringLiteral;
|
||||||
|
I : TSQLIntegerLiteral;
|
||||||
|
|
||||||
|
begin
|
||||||
|
TestSelect('SELECT LEFT(''abc'', 1) FROM A');
|
||||||
|
AssertEquals('One field',1,Select.Fields.Count);
|
||||||
|
AssertEquals('One table',1,Select.Tables.Count);
|
||||||
|
AssertTable(Select.Tables[0],'A');
|
||||||
|
CheckClass(Select.Fields[0],TSQLSelectField);
|
||||||
|
E:=TSQLFunctionCallExpression(CheckClass(TSQLSelectField(Select.Fields[0]).Expression,TSQLFunctionCallExpression));
|
||||||
|
AssertEquals('LEFT function name','LEFT',E.Identifier);
|
||||||
|
AssertEquals('Two function elements',2,E.Arguments.Count);
|
||||||
|
L:=TSQLLiteralExpression(CheckClass(E.Arguments[0],TSQLLiteralExpression));
|
||||||
|
S:=TSQLStringLiteral(CheckClass(L.Literal,TSQLStringLiteral));
|
||||||
|
AssertEquals('Correct string constant','abc',S.Value);
|
||||||
|
L:=TSQLLiteralExpression(CheckClass(E.Arguments[1],TSQLLiteralExpression));
|
||||||
|
I:=TSQLIntegerLiteral(CheckClass(L.Literal,TSQLIntegerLiteral));
|
||||||
|
AssertEquals('Correct integer constant',1,I.Value);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TTestSelectParser.TestNoTable;
|
procedure TTestSelectParser.TestNoTable;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
|
@ -1423,10 +1423,21 @@ type
|
|||||||
//ToDo: proStaticArrayConcat, // concat works with static arrays, returning a dynamic array
|
//ToDo: proStaticArrayConcat, // concat works with static arrays, returning a dynamic array
|
||||||
proProcTypeWithoutIsNested, // proc types can use nested procs without 'is nested'
|
proProcTypeWithoutIsNested, // proc types can use nested procs without 'is nested'
|
||||||
proMethodAddrAsPointer, // can assign @method to a pointer
|
proMethodAddrAsPointer, // can assign @method to a pointer
|
||||||
proSafecallAllowsDefault // allow assigning a default calling convetnion to a SafeCall proc
|
proSafecallAllowsDefault // allow assigning a default calling convention to a SafeCall proc
|
||||||
);
|
);
|
||||||
TPasResolverOptions = set of TPasResolverOption;
|
TPasResolverOptions = set of TPasResolverOption;
|
||||||
|
|
||||||
|
{ TPasResolverHub }
|
||||||
|
|
||||||
|
TPasResolverHub = class
|
||||||
|
private
|
||||||
|
FOwner: TObject;
|
||||||
|
public
|
||||||
|
constructor Create(TheOwner: TObject);
|
||||||
|
property Owner: TObject read FOwner;
|
||||||
|
end;
|
||||||
|
TPasResolverHubClass = class of TPasResolverHub;
|
||||||
|
|
||||||
TPasResolverStep = (
|
TPasResolverStep = (
|
||||||
prsInit,
|
prsInit,
|
||||||
prsParsing,
|
prsParsing,
|
||||||
@ -1480,6 +1491,7 @@ type
|
|||||||
FDefaultScope: TPasDefaultScope;
|
FDefaultScope: TPasDefaultScope;
|
||||||
FDynArrayMaxIndex: TMaxPrecInt;
|
FDynArrayMaxIndex: TMaxPrecInt;
|
||||||
FDynArrayMinIndex: TMaxPrecInt;
|
FDynArrayMinIndex: TMaxPrecInt;
|
||||||
|
FHub: TPasResolverHub;
|
||||||
FLastCreatedData: array[TResolveDataListKind] of TResolveData;
|
FLastCreatedData: array[TResolveDataListKind] of TResolveData;
|
||||||
FLastElement: TPasElement;
|
FLastElement: TPasElement;
|
||||||
FLastMsg: string;
|
FLastMsg: string;
|
||||||
@ -2363,10 +2375,12 @@ type
|
|||||||
function FindLocalBuiltInSymbol(El: TPasElement): TPasElement; virtual;
|
function FindLocalBuiltInSymbol(El: TPasElement): TPasElement; virtual;
|
||||||
function GetFirstSection(WithUnitImpl: boolean): TPasSection;
|
function GetFirstSection(WithUnitImpl: boolean): TPasSection;
|
||||||
function GetLastSection: TPasSection;
|
function GetLastSection: TPasSection;
|
||||||
|
function GetParentSection(El: TPasElement): TPasSection;
|
||||||
function FindUsedUnitInSection(aMod: TPasModule; Section: TPasSection): TPasUsesUnit;
|
function FindUsedUnitInSection(aMod: TPasModule; Section: TPasSection): TPasUsesUnit;
|
||||||
function GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType;
|
function GetShiftAndMaskForLoHiFunc(BaseType: TResolverBaseType;
|
||||||
isLoFunc: Boolean; out Mask: LongWord): Integer;
|
isLoFunc: Boolean; out Mask: LongWord): Integer;
|
||||||
public
|
public
|
||||||
|
property Hub: TPasResolverHub read FHub write FHub;
|
||||||
// options
|
// options
|
||||||
property Options: TPasResolverOptions read FOptions write FOptions;
|
property Options: TPasResolverOptions read FOptions write FOptions;
|
||||||
property AnonymousElTypePostfix: String read FAnonymousElTypePostfix
|
property AnonymousElTypePostfix: String read FAnonymousElTypePostfix
|
||||||
@ -2381,15 +2395,15 @@ type
|
|||||||
property ExprEvaluator: TResExprEvaluator read fExprEvaluator;
|
property ExprEvaluator: TResExprEvaluator read fExprEvaluator;
|
||||||
property DynArrayMinIndex: TMaxPrecInt read FDynArrayMinIndex write FDynArrayMinIndex;
|
property DynArrayMinIndex: TMaxPrecInt read FDynArrayMinIndex write FDynArrayMinIndex;
|
||||||
property DynArrayMaxIndex: TMaxPrecInt read FDynArrayMaxIndex write FDynArrayMaxIndex;
|
property DynArrayMaxIndex: TMaxPrecInt read FDynArrayMaxIndex write FDynArrayMaxIndex;
|
||||||
|
property StoreSrcColumns: boolean read FStoreSrcColumns write FStoreSrcColumns; {
|
||||||
|
If true Line and Column is mangled together in TPasElement.SourceLineNumber.
|
||||||
|
Use method UnmangleSourceLineNumber to extract. }
|
||||||
// parsed values
|
// parsed values
|
||||||
property DefaultNameSpace: String read FDefaultNameSpace;
|
property DefaultNameSpace: String read FDefaultNameSpace;
|
||||||
property RootElement: TPasModule read FRootElement write SetRootElement;
|
property RootElement: TPasModule read FRootElement write SetRootElement;
|
||||||
property Step: TPasResolverStep read FStep;
|
property Step: TPasResolverStep read FStep;
|
||||||
property ActiveHelpers: TPRHelperEntryArray read FActiveHelpers;
|
property ActiveHelpers: TPRHelperEntryArray read FActiveHelpers;
|
||||||
// scopes
|
// scopes
|
||||||
property StoreSrcColumns: boolean read FStoreSrcColumns write FStoreSrcColumns; {
|
|
||||||
If true Line and Column is mangled together in TPasElement.SourceLineNumber.
|
|
||||||
Use method UnmangleSourceLineNumber to extract. }
|
|
||||||
property Scopes[Index: integer]: TPasScope read GetScopes;
|
property Scopes[Index: integer]: TPasScope read GetScopes;
|
||||||
property ScopeCount: integer read FScopeCount;
|
property ScopeCount: integer read FScopeCount;
|
||||||
property TopScope: TPasScope read FTopScope;
|
property TopScope: TPasScope read FTopScope;
|
||||||
@ -3063,6 +3077,13 @@ begin
|
|||||||
str(a,Result);
|
str(a,Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPasResolverHub }
|
||||||
|
|
||||||
|
constructor TPasResolverHub.Create(TheOwner: TObject);
|
||||||
|
begin
|
||||||
|
FOwner:=TheOwner;
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPRSpecializedItem }
|
{ TPRSpecializedItem }
|
||||||
|
|
||||||
destructor TPRSpecializedItem.Destroy;
|
destructor TPRSpecializedItem.Destroy;
|
||||||
@ -11780,6 +11801,8 @@ var
|
|||||||
C: TClass;
|
C: TClass;
|
||||||
ModScope: TPasModuleScope;
|
ModScope: TPasModuleScope;
|
||||||
begin
|
begin
|
||||||
|
if Hub=nil then
|
||||||
|
RaiseNotYetImplemented(20200815182122,El);
|
||||||
if TopScope<>DefaultScope then
|
if TopScope<>DefaultScope then
|
||||||
RaiseInvalidScopeForElement(20160922163504,El);
|
RaiseInvalidScopeForElement(20160922163504,El);
|
||||||
ModScope:=TPasModuleScope(PushScope(El,FScopeClass_Module));
|
ModScope:=TPasModuleScope(PushScope(El,FScopeClass_Module));
|
||||||
@ -29229,6 +29252,16 @@ begin
|
|||||||
Result:=Module.InterfaceSection;
|
Result:=Module.InterfaceSection;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasResolver.GetParentSection(El: TPasElement): TPasSection;
|
||||||
|
begin
|
||||||
|
while El<>nil do
|
||||||
|
begin
|
||||||
|
if El is TPasSection then exit(TPasSection(El));
|
||||||
|
El:=El.Parent;
|
||||||
|
end;
|
||||||
|
Result:=nil;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasResolver.FindUsedUnitInSection(aMod: TPasModule;
|
function TPasResolver.FindUsedUnitInSection(aMod: TPasModule;
|
||||||
Section: TPasSection): TPasUsesUnit;
|
Section: TPasSection): TPasUsesUnit;
|
||||||
var
|
var
|
||||||
|
@ -1750,7 +1750,7 @@ const
|
|||||||
cPasMemberHint : Array[TPasMemberHint] of string =
|
cPasMemberHint : Array[TPasMemberHint] of string =
|
||||||
( 'deprecated', 'library', 'platform', 'experimental', 'unimplemented' );
|
( 'deprecated', 'library', 'platform', 'experimental', 'unimplemented' );
|
||||||
cCallingConventions : Array[TCallingConvention] of string =
|
cCallingConventions : Array[TCallingConvention] of string =
|
||||||
( '', 'Register','Pascal','CDecl','StdCall','OldFPCCall','SafeCall','SysCall','MWPascal',
|
( '', 'Register','Pascal','cdecl','stdcall','OldFPCCall','safecall','SysCall','MWPascal',
|
||||||
'HardFloat','SysV_ABI_Default','SysV_ABI_CDecl',
|
'HardFloat','SysV_ABI_Default','SysV_ABI_CDecl',
|
||||||
'MS_ABI_Default','MS_ABI_CDecl',
|
'MS_ABI_Default','MS_ABI_CDecl',
|
||||||
'VectorCall');
|
'VectorCall');
|
||||||
@ -4208,7 +4208,7 @@ end;
|
|||||||
|
|
||||||
function TPasClassOfType.GetDeclaration (full : boolean) : string;
|
function TPasClassOfType.GetDeclaration (full : boolean) : string;
|
||||||
begin
|
begin
|
||||||
Result:='Class of '+DestType.SafeName;
|
Result:='class of '+DestType.SafeName;
|
||||||
If Full then
|
If Full then
|
||||||
Result:=FixTypeDecl(Result);
|
Result:=FixTypeDecl(Result);
|
||||||
end;
|
end;
|
||||||
|
@ -43,6 +43,8 @@ type
|
|||||||
);
|
);
|
||||||
TPasWriterOptions = Set of TPasWriterOption;
|
TPasWriterOptions = Set of TPasWriterOption;
|
||||||
|
|
||||||
|
TOnUnitAlias = function(const UnitName : String) : String of Object;
|
||||||
|
|
||||||
TPasWriter = class
|
TPasWriter = class
|
||||||
private
|
private
|
||||||
FCurrentLineNumber : Integer;
|
FCurrentLineNumber : Integer;
|
||||||
@ -51,6 +53,7 @@ type
|
|||||||
FForwardClasses: TStrings;
|
FForwardClasses: TStrings;
|
||||||
FLineEnding: String;
|
FLineEnding: String;
|
||||||
FLineNumberWidth: Integer;
|
FLineNumberWidth: Integer;
|
||||||
|
FOnUnitAlias: TOnUnitAlias;
|
||||||
FOPtions: TPasWriterOptions;
|
FOPtions: TPasWriterOptions;
|
||||||
FStream: TStream;
|
FStream: TStream;
|
||||||
FIndentSize : Integer;
|
FIndentSize : Integer;
|
||||||
@ -63,6 +66,7 @@ type
|
|||||||
FInImplementation : Boolean;
|
FInImplementation : Boolean;
|
||||||
procedure SetForwardClasses(AValue: TStrings);
|
procedure SetForwardClasses(AValue: TStrings);
|
||||||
procedure SetIndentSize(AValue: Integer);
|
procedure SetIndentSize(AValue: Integer);
|
||||||
|
function CheckUnitAlias(const AUnitName : String) : String;
|
||||||
protected
|
protected
|
||||||
procedure DisableHintsWarnings;
|
procedure DisableHintsWarnings;
|
||||||
procedure PrepareDeclSectionInStruct(const ADeclSection: string);
|
procedure PrepareDeclSectionInStruct(const ADeclSection: string);
|
||||||
@ -132,6 +136,7 @@ type
|
|||||||
procedure wrtln;overload; deprecated ;
|
procedure wrtln;overload; deprecated ;
|
||||||
property Stream: TStream read FStream;
|
property Stream: TStream read FStream;
|
||||||
Published
|
Published
|
||||||
|
Property OnUnitAlias : TOnUnitAlias Read FOnUnitAlias Write FOnUnitAlias;
|
||||||
Property Options : TPasWriterOptions Read FOPtions Write FOptions;
|
Property Options : TPasWriterOptions Read FOPtions Write FOptions;
|
||||||
Property IndentSize : Integer Read FIndentSize Write SetIndentSize;
|
Property IndentSize : Integer Read FIndentSize Write SetIndentSize;
|
||||||
Property LineEnding : String Read FLineEnding Write FLineEnding;
|
Property LineEnding : String Read FLineEnding Write FLineEnding;
|
||||||
@ -478,7 +483,7 @@ end;
|
|||||||
procedure TPasWriter.WriteUnit(aModule: TPasModule);
|
procedure TPasWriter.WriteUnit(aModule: TPasModule);
|
||||||
|
|
||||||
begin
|
begin
|
||||||
AddLn('unit ' + AModule.SafeName + ';');
|
AddLn('unit ' + CheckUnitAlias(AModule.SafeName) + ';');
|
||||||
if Assigned(AModule.GlobalDirectivesSection) then
|
if Assigned(AModule.GlobalDirectivesSection) then
|
||||||
begin
|
begin
|
||||||
AddLn;
|
AddLn;
|
||||||
@ -556,7 +561,7 @@ Var
|
|||||||
Add(', ')
|
Add(', ')
|
||||||
else
|
else
|
||||||
Add('uses ');
|
Add('uses ');
|
||||||
Add(AName);
|
Add(CheckUnitAlias(AName));
|
||||||
if (AUnitFile<>Nil) then
|
if (AUnitFile<>Nil) then
|
||||||
Add(' in '+GetExpr(AUnitFile));
|
Add(' in '+GetExpr(AUnitFile));
|
||||||
Inc(c);
|
Inc(c);
|
||||||
@ -848,9 +853,7 @@ end;
|
|||||||
procedure TPasWriter.WriteRecordType(AType: TPasRecordType);
|
procedure TPasWriter.WriteRecordType(AType: TPasRecordType);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
I : Integer;
|
|
||||||
Temp : String;
|
Temp : String;
|
||||||
el : TPasElement;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
Temp:='record';
|
Temp:='record';
|
||||||
@ -1490,6 +1493,14 @@ begin
|
|||||||
FIndentStep:=StringOfChar(' ',aValue);
|
FIndentStep:=StringOfChar(' ',aValue);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPasWriter.CheckUnitAlias(const AUnitName: String): String;
|
||||||
|
begin
|
||||||
|
if Assigned(FOnUnitAlias) then
|
||||||
|
Result := FOnUnitAlias(AUnitName)
|
||||||
|
else
|
||||||
|
Result := AUnitName;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPasWriter.HasOption(aOption: TPasWriterOption): Boolean;
|
function TPasWriter.HasOption(aOption: TPasWriterOption): Boolean;
|
||||||
begin
|
begin
|
||||||
Result:=(aOption in FOptions)
|
Result:=(aOption in FOptions)
|
||||||
|
@ -112,6 +112,7 @@ type
|
|||||||
|
|
||||||
TCustomTestResolver = Class(TTestParser)
|
TCustomTestResolver = Class(TTestParser)
|
||||||
Private
|
Private
|
||||||
|
FHub: TPasResolverHub;
|
||||||
{$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
|
{$IF defined(VerbosePasResolver) or defined(VerbosePasResolverMem)}
|
||||||
FStartElementRefCount: int64;
|
FStartElementRefCount: int64;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -173,6 +174,7 @@ type
|
|||||||
procedure StartUnit(NeedSystemUnit: boolean);
|
procedure StartUnit(NeedSystemUnit: boolean);
|
||||||
property Modules[Index: integer]: TTestEnginePasResolver read GetModules;
|
property Modules[Index: integer]: TTestEnginePasResolver read GetModules;
|
||||||
property ModuleCount: integer read GetModuleCount;
|
property ModuleCount: integer read GetModuleCount;
|
||||||
|
property Hub: TPasResolverHub read FHub;
|
||||||
property ResolverEngine: TTestEnginePasResolver read FResolverEngine;
|
property ResolverEngine: TTestEnginePasResolver read FResolverEngine;
|
||||||
property MsgCount: integer read GetMsgCount;
|
property MsgCount: integer read GetMsgCount;
|
||||||
property Msgs[Index: integer]: TTestResolverMessage read GetMsgs;
|
property Msgs[Index: integer]: TTestResolverMessage read GetMsgs;
|
||||||
@ -1060,6 +1062,7 @@ begin
|
|||||||
FStartElementRefCount:=TPasElement.GlobalRefCount;
|
FStartElementRefCount:=TPasElement.GlobalRefCount;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
FModules:=TObjectList.Create(true);
|
FModules:=TObjectList.Create(true);
|
||||||
|
FHub:=TPasResolverHub.Create(Self);
|
||||||
inherited SetUp;
|
inherited SetUp;
|
||||||
Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
|
Parser.Options:=Parser.Options+[po_ResolveStandardTypes];
|
||||||
Scanner.OnDirective:=@OnScannerDirective;
|
Scanner.OnDirective:=@OnScannerDirective;
|
||||||
@ -1096,6 +1099,7 @@ begin
|
|||||||
FModules.OwnsObjects:=true;
|
FModules.OwnsObjects:=true;
|
||||||
FreeAndNil(FModules);// free all other modules
|
FreeAndNil(FModules);// free all other modules
|
||||||
end;
|
end;
|
||||||
|
FreeAndNil(FHub);
|
||||||
{$IFDEF VerbosePasResolverMem}
|
{$IFDEF VerbosePasResolverMem}
|
||||||
writeln('TTestResolver.TearDown inherited');
|
writeln('TTestResolver.TearDown inherited');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
@ -2171,6 +2175,7 @@ begin
|
|||||||
Result.AddObjFPCBuiltInIdentifiers;
|
Result.AddObjFPCBuiltInIdentifiers;
|
||||||
Result.OnFindUnit:=@OnPasResolverFindUnit;
|
Result.OnFindUnit:=@OnPasResolverFindUnit;
|
||||||
Result.OnLog:=@OnPasResolverLog;
|
Result.OnLog:=@OnPasResolverLog;
|
||||||
|
Result.Hub:=Hub;
|
||||||
FModules.Add(Result);
|
FModules.Add(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1369,6 +1369,11 @@ type
|
|||||||
property TargetProcessor: TPasToJsProcessor read FTargetProcessor write FTargetProcessor;
|
property TargetProcessor: TPasToJsProcessor read FTargetProcessor write FTargetProcessor;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ TPas2JSResolverHub }
|
||||||
|
|
||||||
|
TPas2JSResolverHub = class(TPasResolverHub)
|
||||||
|
end;
|
||||||
|
|
||||||
{ TPas2JSResolver }
|
{ TPas2JSResolver }
|
||||||
|
|
||||||
TPas2JSResolver = class(TPasResolver)
|
TPas2JSResolver = class(TPasResolver)
|
||||||
@ -1473,6 +1478,7 @@ type
|
|||||||
// generic/specialize
|
// generic/specialize
|
||||||
procedure SpecializeGenericImpl(SpecializedItem: TPRSpecializedItem);
|
procedure SpecializeGenericImpl(SpecializedItem: TPRSpecializedItem);
|
||||||
override;
|
override;
|
||||||
|
function SpecializeNeedsDelay(SpecializedItem: TPRSpecializedItem): TPasElement;
|
||||||
protected
|
protected
|
||||||
const
|
const
|
||||||
cJSValueConversion = 2*cTypeConversion;
|
cJSValueConversion = 2*cTypeConversion;
|
||||||
@ -4900,6 +4906,47 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TPas2JSResolver.SpecializeNeedsDelay(
|
||||||
|
SpecializedItem: TPRSpecializedItem): TPasElement;
|
||||||
|
// finds first specialize param defined later than the generic
|
||||||
|
// For example: generic in the unit interface, param in implementation
|
||||||
|
// or param in another unit, not used by the generic
|
||||||
|
var
|
||||||
|
Gen: TPasElement;
|
||||||
|
GenMod, ParamMod: TPasModule;
|
||||||
|
Params: TPasTypeArray;
|
||||||
|
Param: TPasType;
|
||||||
|
i: Integer;
|
||||||
|
GenSection, ParamSection: TPasSection;
|
||||||
|
begin
|
||||||
|
Result:=nil;
|
||||||
|
Gen:=SpecializedItem.GenericEl;
|
||||||
|
GenSection:=GetParentSection(Gen);
|
||||||
|
if not (GenSection is TInterfaceSection) then
|
||||||
|
exit; // generic in unit implementation/program/library -> params cannot be defined a later section
|
||||||
|
GenMod:=GenSection.GetModule;
|
||||||
|
|
||||||
|
Params:=SpecializedItem.Params;
|
||||||
|
for i:=0 to length(Params)-1 do
|
||||||
|
begin
|
||||||
|
Param:=ResolveAliasType(Params[i],false);
|
||||||
|
if Param.ClassType=TPasUnresolvedSymbolRef then
|
||||||
|
continue; // built-in type
|
||||||
|
ParamSection:=GetParentSection(Param);
|
||||||
|
if ParamSection=GenSection then continue;
|
||||||
|
// not in same section
|
||||||
|
ParamMod:=ParamSection.GetModule;
|
||||||
|
if ParamMod=GenMod then
|
||||||
|
exit(Param); // generic in unit interface, specialize in implementation
|
||||||
|
// param in another unit
|
||||||
|
if ParamSection is TImplementationSection then
|
||||||
|
exit(Param); // generic in unit interface, specialize in another(later) implementation
|
||||||
|
// param in another unit interface
|
||||||
|
|
||||||
|
//xxx
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function TPas2JSResolver.AddJSBaseType(const aName: string; Typ: TPas2jsBaseType
|
function TPas2JSResolver.AddJSBaseType(const aName: string; Typ: TPas2jsBaseType
|
||||||
): TResElDataPas2JSBaseType;
|
): TResElDataPas2JSBaseType;
|
||||||
var
|
var
|
||||||
|
@ -500,6 +500,7 @@ type
|
|||||||
FPostProcessorSupport: TPas2JSPostProcessorSupport;
|
FPostProcessorSupport: TPas2JSPostProcessorSupport;
|
||||||
FPrecompileGUID: TGUID;
|
FPrecompileGUID: TGUID;
|
||||||
FReadingModules: TFPList; // list of TPas2jsCompilerFile ordered by uses sections
|
FReadingModules: TFPList; // list of TPas2jsCompilerFile ordered by uses sections
|
||||||
|
FResolverHub: TPas2JSResolverHub;
|
||||||
FRTLVersionCheck: TP2jsRTLVersionCheck;
|
FRTLVersionCheck: TP2jsRTLVersionCheck;
|
||||||
FSrcMapBaseDir: string;
|
FSrcMapBaseDir: string;
|
||||||
FSrcMapSourceRoot: string;
|
FSrcMapSourceRoot: string;
|
||||||
@ -680,14 +681,15 @@ type
|
|||||||
property DefaultNamespace: String read GetDefaultNamespace;
|
property DefaultNamespace: String read GetDefaultNamespace;
|
||||||
property Defines: TStrings read FDefines;
|
property Defines: TStrings read FDefines;
|
||||||
property FS: TPas2jsFS read FFS write SetFS;
|
property FS: TPas2jsFS read FFS write SetFS;
|
||||||
property OwnsFS: boolean read FOwnsFS write FOwnsFS;
|
property OwnsFS: boolean read FOwnsFS write FOwnsFS; // true = auto free FS when compiler is freed
|
||||||
property FileCount: integer read GetFileCount;
|
property FileCount: integer read GetFileCount;
|
||||||
property InterfaceType: TPasClassInterfaceType read FInterfaceType write FInterfaceType;
|
property InterfaceType: TPasClassInterfaceType read FInterfaceType write FInterfaceType; // default interface type
|
||||||
property Log: TPas2jsLogger read FLog;
|
property Log: TPas2jsLogger read FLog;
|
||||||
property MainFile: TPas2jsCompilerFile read FMainFile;
|
property MainFile: TPas2jsCompilerFile read FMainFile;
|
||||||
property ModeSwitches: TModeSwitches read FModeSwitches write SetModeSwitches;
|
property ModeSwitches: TModeSwitches read FModeSwitches write SetModeSwitches;
|
||||||
property Options: TP2jsCompilerOptions read FOptions write SetOptions;
|
property Options: TP2jsCompilerOptions read FOptions write SetOptions;
|
||||||
property ConverterGlobals: TPasToJSConverterGlobals read FConverterGlobals write SetConverterGlobals;
|
property ConverterGlobals: TPasToJSConverterGlobals read FConverterGlobals write SetConverterGlobals;
|
||||||
|
property ResolverHub: TPas2JSResolverHub read FResolverHub;
|
||||||
property ParamMacros: TPas2jsMacroEngine read FParamMacros;
|
property ParamMacros: TPas2jsMacroEngine read FParamMacros;
|
||||||
property PrecompileGUID: TGUID read FPrecompileGUID write FPrecompileGUID;
|
property PrecompileGUID: TGUID read FPrecompileGUID write FPrecompileGUID;
|
||||||
property RTLVersionCheck: TP2jsRTLVersionCheck read FRTLVersionCheck write FRTLVersionCheck;
|
property RTLVersionCheck: TP2jsRTLVersionCheck read FRTLVersionCheck write FRTLVersionCheck;
|
||||||
@ -965,6 +967,7 @@ begin
|
|||||||
FPasResolver.OnCheckSrcName:=@OnResolverCheckSrcName;
|
FPasResolver.OnCheckSrcName:=@OnResolverCheckSrcName;
|
||||||
FPasResolver.OnLog:=@OnPasResolverLog;
|
FPasResolver.OnLog:=@OnPasResolverLog;
|
||||||
FPasResolver.Log:=Log;
|
FPasResolver.Log:=Log;
|
||||||
|
FPasResolver.Hub:=aCompiler.ResolverHub;
|
||||||
FPasResolver.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
|
FPasResolver.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
|
||||||
FIsMainFile:=Compiler.FS.SameFileName(Compiler.MainSrcFile,PasFilename);
|
FIsMainFile:=Compiler.FS.SameFileName(Compiler.MainSrcFile,PasFilename);
|
||||||
for ub in TUsedBySection do
|
for ub in TUsedBySection do
|
||||||
@ -4191,6 +4194,7 @@ constructor TPas2jsCompiler.Create;
|
|||||||
begin
|
begin
|
||||||
FOptions:=DefaultP2jsCompilerOptions;
|
FOptions:=DefaultP2jsCompilerOptions;
|
||||||
FConverterGlobals:=TPasToJSConverterGlobals.Create(Self);
|
FConverterGlobals:=TPasToJSConverterGlobals.Create(Self);
|
||||||
|
FResolverHub:=TPas2JSResolverHub.Create(Self);
|
||||||
FNamespaces:=TStringList.Create;
|
FNamespaces:=TStringList.Create;
|
||||||
FDefines:=TStringList.Create;
|
FDefines:=TStringList.Create;
|
||||||
FInsertFilenames:=TStringList.Create;
|
FInsertFilenames:=TStringList.Create;
|
||||||
@ -4232,6 +4236,7 @@ destructor TPas2jsCompiler.Destroy;
|
|||||||
FreeAndNil(FPostProcessorSupport);
|
FreeAndNil(FPostProcessorSupport);
|
||||||
FreeAndNil(FConfigSupport);
|
FreeAndNil(FConfigSupport);
|
||||||
ConverterGlobals:=nil;
|
ConverterGlobals:=nil;
|
||||||
|
FreeAndNil(FResolverHub);
|
||||||
|
|
||||||
ClearDefines;
|
ClearDefines;
|
||||||
FreeAndNil(FDefines);
|
FreeAndNil(FDefines);
|
||||||
|
@ -67,6 +67,7 @@ type
|
|||||||
procedure TestGenProc_TypeInfo;
|
procedure TestGenProc_TypeInfo;
|
||||||
procedure TestGenProc_Infer_Widen;
|
procedure TestGenProc_Infer_Widen;
|
||||||
procedure TestGenProc_Infer_PassAsArg;
|
procedure TestGenProc_Infer_PassAsArg;
|
||||||
|
// ToDo: delay create: type TRec=record end; ... r:=GenProc<TRec>();
|
||||||
// ToDo: FuncName:= instead of Result:=
|
// ToDo: FuncName:= instead of Result:=
|
||||||
|
|
||||||
// generic methods
|
// generic methods
|
||||||
|
@ -111,6 +111,7 @@ type
|
|||||||
FExpectedErrorNumber: integer;
|
FExpectedErrorNumber: integer;
|
||||||
FFilename: string;
|
FFilename: string;
|
||||||
FFileResolver: TStreamResolver;
|
FFileResolver: TStreamResolver;
|
||||||
|
FHub: TPas2JSResolverHub;
|
||||||
FJSImplementationSrc: TJSSourceElements;
|
FJSImplementationSrc: TJSSourceElements;
|
||||||
FJSImplementationUses: TJSArrayLiteral;
|
FJSImplementationUses: TJSArrayLiteral;
|
||||||
FJSInitBody: TJSFunctionBody;
|
FJSInitBody: TJSFunctionBody;
|
||||||
@ -216,6 +217,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create; override;
|
constructor Create; override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
|
property Hub: TPas2JSResolverHub read FHub;
|
||||||
property Source: TStringList read FSource;
|
property Source: TStringList read FSource;
|
||||||
property FileResolver: TStreamResolver read FFileResolver;
|
property FileResolver: TStreamResolver read FFileResolver;
|
||||||
property Scanner: TPas2jsPasScanner read FScanner;
|
property Scanner: TPas2jsPasScanner read FScanner;
|
||||||
@ -1310,6 +1312,8 @@ begin
|
|||||||
inherited SetUp;
|
inherited SetUp;
|
||||||
FSkipTests:=false;
|
FSkipTests:=false;
|
||||||
FSource:=TStringList.Create;
|
FSource:=TStringList.Create;
|
||||||
|
|
||||||
|
FHub:=TPas2JSResolverHub.Create(Self);
|
||||||
FModules:=TObjectList.Create(true);
|
FModules:=TObjectList.Create(true);
|
||||||
|
|
||||||
FFilename:='test1.pp';
|
FFilename:='test1.pp';
|
||||||
@ -1404,6 +1408,7 @@ begin
|
|||||||
ReleaseAndNil(TPasElement(FModule){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
|
ReleaseAndNil(TPasElement(FModule){$IFDEF CheckPasTreeRefCount},'CreateElement'{$ENDIF});
|
||||||
FEngine:=nil;
|
FEngine:=nil;
|
||||||
end;
|
end;
|
||||||
|
FreeAndNil(FHub);
|
||||||
|
|
||||||
inherited TearDown;
|
inherited TearDown;
|
||||||
{$IFDEF EnablePasTreeGlobalRefCount}
|
{$IFDEF EnablePasTreeGlobalRefCount}
|
||||||
@ -1558,6 +1563,7 @@ begin
|
|||||||
Result.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
|
Result.AddObjFPCBuiltInIdentifiers(btAllJSBaseTypes,bfAllJSBaseProcs);
|
||||||
Result.OnFindUnit:=@OnPasResolverFindUnit;
|
Result.OnFindUnit:=@OnPasResolverFindUnit;
|
||||||
Result.OnLog:=@OnPasResolverLog;
|
Result.OnLog:=@OnPasResolverLog;
|
||||||
|
Result.Hub:=Hub;
|
||||||
FModules.Add(Result);
|
FModules.Add(Result);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -56,7 +56,8 @@ interface
|
|||||||
{$BOOLEVAL OFF}
|
{$BOOLEVAL OFF}
|
||||||
{$EXTENDEDSYNTAX ON}
|
{$EXTENDEDSYNTAX ON}
|
||||||
{$LONGSTRINGS ON}
|
{$LONGSTRINGS ON}
|
||||||
{$OPTIMIZATION ON}
|
{ use optimization settings passed via fpmake/make }
|
||||||
|
{OPTIMIZATION ON}
|
||||||
|
|
||||||
// ======== Define options for TRegExpr engine
|
// ======== Define options for TRegExpr engine
|
||||||
{$DEFINE UseFirstCharSet} // Enable optimization, which finds possible first chars of input string
|
{$DEFINE UseFirstCharSet} // Enable optimization, which finds possible first chars of input string
|
||||||
|
@ -325,6 +325,7 @@ unit ComObj;
|
|||||||
CoResumeClassObjects : TCoResumeClassObjectsProc = nil;
|
CoResumeClassObjects : TCoResumeClassObjectsProc = nil;
|
||||||
CoSuspendClassObjects : TCoSuspendClassObjectsProc = nil;
|
CoSuspendClassObjects : TCoSuspendClassObjectsProc = nil;
|
||||||
CoInitFlags : Longint = -1;
|
CoInitFlags : Longint = -1;
|
||||||
|
CoInitDisable : Boolean = False;
|
||||||
|
|
||||||
{$ifdef DEBUG_COM}
|
{$ifdef DEBUG_COM}
|
||||||
var printcom : boolean=true;
|
var printcom : boolean=true;
|
||||||
@ -1877,6 +1878,20 @@ const
|
|||||||
Initialized : boolean = false;
|
Initialized : boolean = false;
|
||||||
var
|
var
|
||||||
Ole32Dll : HModule;
|
Ole32Dll : HModule;
|
||||||
|
SaveInitProc : CodePointer;
|
||||||
|
|
||||||
|
procedure InitComObj;
|
||||||
|
begin
|
||||||
|
if SaveInitProc<>nil then
|
||||||
|
TProcedure(SaveInitProc)();
|
||||||
|
if not CoInitDisable then
|
||||||
|
{$ifndef wince}
|
||||||
|
if (CoInitFlags=-1) or not(assigned(ComObj.CoInitializeEx)) then
|
||||||
|
Initialized:=Succeeded(CoInitialize(nil))
|
||||||
|
else
|
||||||
|
{$endif wince}
|
||||||
|
Initialized:=Succeeded(ComObj.CoInitializeEx(nil, CoInitFlags));
|
||||||
|
end;
|
||||||
|
|
||||||
initialization
|
initialization
|
||||||
Uninitializing:=false;
|
Uninitializing:=false;
|
||||||
@ -1893,12 +1908,10 @@ initialization
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
if not(IsLibrary) then
|
if not(IsLibrary) then
|
||||||
{$ifndef wince}
|
begin
|
||||||
if (CoInitFlags=-1) or not(assigned(comobj.CoInitializeEx)) then
|
SaveInitProc:=InitProc;
|
||||||
Initialized:=Succeeded(CoInitialize(nil))
|
InitProc:=@InitComObj;
|
||||||
else
|
end;
|
||||||
{$endif wince}
|
|
||||||
Initialized:=Succeeded(comobj.CoInitializeEx(nil, CoInitFlags));
|
|
||||||
|
|
||||||
SafeCallErrorProc:=@SafeCallErrorHandler;
|
SafeCallErrorProc:=@SafeCallErrorHandler;
|
||||||
VarDispProc:=@ComObjDispatchInvoke;
|
VarDispProc:=@ComObjDispatchInvoke;
|
||||||
|
@ -169,7 +169,7 @@ finalization
|
|||||||
Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
|
Writeln(pstdout^,'Runtime error ',Errorcode,' at $',hexstr(erroraddr));
|
||||||
{ to get a nice symify }
|
{ to get a nice symify }
|
||||||
Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
|
Writeln(pstdout^,BackTraceStrFunc(Erroraddr));
|
||||||
dump_stack(pstdout^,ErrorBase);
|
dump_stack(pstdout^,ErrorBase,erroraddr);
|
||||||
Writeln(pstdout^,'');
|
Writeln(pstdout^,'');
|
||||||
End;
|
End;
|
||||||
SysFlushStdIO;
|
SysFlushStdIO;
|
||||||
|
@ -208,6 +208,7 @@ const calculated_cmdline:Pchar=nil;
|
|||||||
{*****************************************************************************
|
{*****************************************************************************
|
||||||
Misc. System Dependent Functions
|
Misc. System Dependent Functions
|
||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
{$ifndef FPC_SYSTEM_HAS_STACKTOP}
|
||||||
var
|
var
|
||||||
_stack_top: record end; external name '_stack_top';
|
_stack_top: record end; external name '_stack_top';
|
||||||
|
|
||||||
@ -215,6 +216,7 @@ function StackTop: pointer;
|
|||||||
begin
|
begin
|
||||||
StackTop:=@_stack_top;
|
StackTop:=@_stack_top;
|
||||||
end;
|
end;
|
||||||
|
{$endif FPC_SYSTEM_HAS_STACKTOP}
|
||||||
|
|
||||||
|
|
||||||
procedure haltproc;cdecl;external name '_haltproc';
|
procedure haltproc;cdecl;external name '_haltproc';
|
||||||
|
@ -62,8 +62,7 @@ Procedure ResetFPU;
|
|||||||
var
|
var
|
||||||
l_fpucw : longint;
|
l_fpucw : longint;
|
||||||
begin
|
begin
|
||||||
|
{$if defined(FPU68881) or defined(FPUCOLDFIRE)}
|
||||||
{$ifdef CPU68020}
|
|
||||||
asm
|
asm
|
||||||
fmove.l fpcr,l_fpucw
|
fmove.l fpcr,l_fpucw
|
||||||
end;
|
end;
|
||||||
|
@ -23,8 +23,8 @@ type
|
|||||||
|
|
||||||
pfpstate = ^tfpstate;
|
pfpstate = ^tfpstate;
|
||||||
tfpstate = record
|
tfpstate = record
|
||||||
pcr,psr,fpiaddr : longint;
|
pcr,psr,fpiaddr : longint;
|
||||||
fpreg : array [0..7] of tfpreg;
|
fpreg : array [0..7] of tfpreg;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ as defined in asm_m68k/signal.h }
|
{ as defined in asm_m68k/signal.h }
|
||||||
|
@ -31,27 +31,114 @@ begin
|
|||||||
SysInitFPU;
|
SysInitFPU;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{$ifdef fpc_abi_windowed}
|
||||||
|
const
|
||||||
|
// Minimum call8 calls to force register spilling to stack for caller of forceSpilledRegs
|
||||||
|
spillcount = 6;
|
||||||
|
|
||||||
|
procedure forceSpilledRegs(n: uint32); assembler; public name 'forcespilledregs';
|
||||||
|
label
|
||||||
|
done, fin;
|
||||||
|
asm
|
||||||
|
beqz a2, done
|
||||||
|
addi a10, a2, -1
|
||||||
|
call8 forcespilledregs
|
||||||
|
done:
|
||||||
|
bnez a2, fin
|
||||||
|
movi a15, 0
|
||||||
|
fin:
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure fixCodeAddress(var addr: pointer);
|
||||||
|
begin
|
||||||
|
// Check if valid code address
|
||||||
|
if ptruint(addr) and $C0000000 >= $40000000 then
|
||||||
|
begin
|
||||||
|
// Replace windowed call prefix
|
||||||
|
addr:=codepointer((ptruint(addr)and$00FFFFFF) or $40000000);
|
||||||
|
// Rewind to call instruction address
|
||||||
|
dec(addr,3);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
addr:=nil;
|
||||||
|
end;
|
||||||
|
{$endif fpc_abi_windowed}
|
||||||
|
|
||||||
{$IFNDEF INTERNAL_BACKTRACE}
|
{$IFNDEF INTERNAL_BACKTRACE}
|
||||||
{$define FPC_SYSTEM_HAS_GET_FRAME}
|
{$define FPC_SYSTEM_HAS_GET_FRAME}
|
||||||
function get_frame:pointer;assembler;nostackframe;
|
function get_frame:pointer;assembler;
|
||||||
asm
|
label
|
||||||
end;
|
done;
|
||||||
|
asm
|
||||||
|
{$ifdef fpc_abi_windowed}
|
||||||
|
// Force registers to spill onto stack
|
||||||
|
movi a10, spillcount
|
||||||
|
call8 forcespilledregs
|
||||||
|
// now get frame pointer of caller
|
||||||
|
addi a2, a1, -12
|
||||||
|
l32i a2, a2, 0
|
||||||
|
done:
|
||||||
|
{$else}
|
||||||
|
mov a2, a1
|
||||||
|
{$endif}
|
||||||
|
end;
|
||||||
{$ENDIF not INTERNAL_BACKTRACE}
|
{$ENDIF not INTERNAL_BACKTRACE}
|
||||||
|
|
||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
|
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
|
||||||
function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
|
function get_caller_addr(framebp:pointer;addr:pointer=nil):pointer;
|
||||||
asm
|
begin
|
||||||
|
{$ifdef fpc_abi_windowed}
|
||||||
|
forceSpilledRegs(spillcount);
|
||||||
|
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
|
||||||
|
begin
|
||||||
|
get_caller_addr:=pointer((framebp-16)^);
|
||||||
|
fixCodeAddress(get_caller_addr);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
get_caller_addr:=nil;
|
||||||
|
{$else}
|
||||||
|
get_caller_addr:=nil;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
|
{$define FPC_SYSTEM_HAS_GET_CALLER_FRAME}
|
||||||
function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;assembler;nostackframe;
|
function get_caller_frame(framebp:pointer;addr:pointer=nil):pointer;
|
||||||
asm
|
begin
|
||||||
|
{$ifdef fpc_abi_windowed}
|
||||||
|
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
|
||||||
|
begin
|
||||||
|
forceSpilledRegs(spillcount);
|
||||||
|
get_caller_frame:=pointer((framebp-12)^);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
get_caller_frame:=nil;
|
||||||
|
{$else}
|
||||||
|
get_caller_frame:=nil;
|
||||||
|
{$endif}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{$ifdef fpc_abi_windowed}
|
||||||
|
{$define FPC_SYSTEM_HAS_GET_CALLER_STACKINFO}
|
||||||
|
procedure get_caller_stackinfo(var framebp : pointer; var addr : codepointer);
|
||||||
|
begin
|
||||||
|
if (ptruint(framebp)>$3ff00000)and(ptruint(framebp)<$40000000) then
|
||||||
|
begin
|
||||||
|
forceSpilledRegs(spillcount);
|
||||||
|
addr:=codepointer((framebp-16)^);
|
||||||
|
framebp := pointer((framebp-12)^);
|
||||||
|
fixCodeAddress(addr);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
addr:=nil;
|
||||||
|
framebp:=nil;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$endif fpc_abi_windowed}
|
||||||
|
|
||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_SPTR}
|
{$define FPC_SYSTEM_HAS_SPTR}
|
||||||
Function Sptr : pointer;assembler;
|
Function Sptr : pointer;assembler;
|
||||||
asm
|
asm
|
||||||
@ -59,6 +146,16 @@ Function Sptr : pointer;assembler;
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{$define FPC_SYSTEM_HAS_STACKTOP}
|
||||||
|
// Interim fix for now, set to large address
|
||||||
|
// TODO: provide more realistic value, possibly by inspecting stack pointer
|
||||||
|
// when main or task is started
|
||||||
|
function StackTop: pointer;
|
||||||
|
begin
|
||||||
|
StackTop:=pointer($3fffffff);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
function InterLockedDecrement (var Target: longint) : longint;
|
function InterLockedDecrement (var Target: longint) : longint;
|
||||||
var
|
var
|
||||||
temp_sreg : byte;
|
temp_sreg : byte;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{ in tp mode can't use the procvar in writeln OK 0.99.11 (PFV) }
|
{ in tp mode can't use the procvar in writeln OK 0.99.11 (PFV) }
|
||||||
|
|
||||||
{$ifdef fpc}{$mode tp}{$endif}
|
{$ifdef fpc}{$mode tp}{$endif}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
type tmpproc=function:longint;
|
type tmpproc=function:longint;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{ problem with procvars in tp mode OK 0.99.11 (PM) }
|
{ problem with procvars in tp mode OK 0.99.11 (PM) }
|
||||||
|
|
||||||
{$mode tp}
|
{$mode tp}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
type proc = procedure(a : longint);
|
type proc = procedure(a : longint);
|
||||||
procedure test(b : longint);
|
procedure test(b : longint);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{ @procvar in tp mode bugss OK 0.99.13 (PFV) }
|
{ @procvar in tp mode bugss OK 0.99.13 (PFV) }
|
||||||
|
|
||||||
{$ifdef fpc}{$mode tp}{$endif}
|
{$ifdef fpc}{$mode tp}{$endif}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
function ReturnString: string;
|
function ReturnString: string;
|
||||||
begin
|
begin
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
type
|
type
|
||||||
codepointer = pointer;
|
codepointer = pointer;
|
||||||
{$endif fpc}
|
{$endif fpc}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
function times2(x : longint) : longint;
|
function times2(x : longint) : longint;
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ program taddr;
|
|||||||
{$ifdef fpc}
|
{$ifdef fpc}
|
||||||
{$mode tp}
|
{$mode tp}
|
||||||
{$endif}
|
{$endif}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
procedure testprocvar;
|
procedure testprocvar;
|
||||||
begin
|
begin
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{$F+}
|
|
||||||
{$ifdef fpc}
|
{$ifdef fpc}
|
||||||
{$mode tp}
|
{$mode tp}
|
||||||
{$endif fpc}
|
{$endif fpc}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
type
|
type
|
||||||
tproc = procedure;
|
tproc = procedure;
|
||||||
|
5
tests/webtbf/tw37476.pp
Normal file
5
tests/webtbf/tw37476.pp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{ %fail }
|
||||||
|
var a : string = (a >= 'A') and (a <= 'F');
|
||||||
|
|
||||||
|
begin
|
||||||
|
end.
|
@ -1,4 +1,5 @@
|
|||||||
{$mode tp}
|
{$mode tp}
|
||||||
|
{$F+}
|
||||||
type ProcType = procedure(s:string);
|
type ProcType = procedure(s:string);
|
||||||
GetProcType = function(s:string;var Proc:ProcType):boolean;
|
GetProcType = function(s:string;var Proc:ProcType):boolean;
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
{ Submitted by "marco" on 2002-12-19 }
|
{ Submitted by "marco" on 2002-12-19 }
|
||||||
{ e-mail: marco@freepascal.org }
|
{ e-mail: marco@freepascal.org }
|
||||||
{$ifdef fpc}{$mode TP}{$endif}
|
{$ifdef fpc}{$mode TP}{$endif}
|
||||||
|
{$F+}
|
||||||
|
|
||||||
function P1:longint; begin end;
|
function P1:longint; begin end;
|
||||||
function P2:longint; begin end;
|
function P2:longint; begin end;
|
||||||
|
@ -147,6 +147,17 @@ begin
|
|||||||
Move(C[1],AErrorClass^,L);
|
Move(C[1],AErrorClass^,L);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Procedure SetStubCreatorUnitAliasCallBack(P : PStubCreator; ACallBack : TUnitAliasCallBack; CallBackData : Pointer); stdcall;
|
||||||
|
begin
|
||||||
|
TStubCreator(P).OnUnitAlias:=ACallBack;
|
||||||
|
TStubCreator(P).OnUnitAliasData:=CallBackData;
|
||||||
|
end;
|
||||||
|
|
||||||
|
Procedure AddStubCreatorExtraUnit(P : PStubCreator; AUnitName : PAnsiChar); stdcall;
|
||||||
|
begin
|
||||||
|
TStubCreator(P).ExtraUnits:=AUnitName;
|
||||||
|
end;
|
||||||
|
|
||||||
exports
|
exports
|
||||||
// Stub creator
|
// Stub creator
|
||||||
GetStubCreator,
|
GetStubCreator,
|
||||||
@ -160,7 +171,9 @@ exports
|
|||||||
GetStubCreatorLastError,
|
GetStubCreatorLastError,
|
||||||
AddStubCreatorDefine,
|
AddStubCreatorDefine,
|
||||||
AddStubCreatorForwardClass,
|
AddStubCreatorForwardClass,
|
||||||
ExecuteStubCreator;
|
AddStubCreatorExtraUnit,
|
||||||
|
ExecuteStubCreator,
|
||||||
|
SetStubCreatorUnitAliasCallBack;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
@ -19,9 +19,6 @@ interface
|
|||||||
uses
|
uses
|
||||||
Classes, SysUtils, strutils, inifiles, pscanner, pparser, pastree, iostream, paswrite;
|
Classes, SysUtils, strutils, inifiles, pscanner, pparser, pastree, iostream, paswrite;
|
||||||
|
|
||||||
Const
|
|
||||||
DTypesUnit = 'jsdelphisystem';
|
|
||||||
|
|
||||||
type
|
type
|
||||||
{ We have to override abstract TPasTreeContainer methods }
|
{ We have to override abstract TPasTreeContainer methods }
|
||||||
|
|
||||||
@ -36,6 +33,8 @@ type
|
|||||||
|
|
||||||
TWriteCallBack = Procedure (Data : Pointer; AFileData : PAnsiChar; AFileDataLen: Int32); stdcall;
|
TWriteCallBack = Procedure (Data : Pointer; AFileData : PAnsiChar; AFileDataLen: Int32); stdcall;
|
||||||
TWriteEvent = Procedure(AFileData : String) of object;
|
TWriteEvent = Procedure(AFileData : String) of object;
|
||||||
|
TUnitAliasCallBack = Function (Data: Pointer; AUnitName: PAnsiChar;
|
||||||
|
var AUnitNameMaxLen: Int32): boolean; {$IFDEF UseCDecl}cdecl{$ELSE}stdcall{$ENDIF};
|
||||||
|
|
||||||
{ TStubCreator }
|
{ TStubCreator }
|
||||||
|
|
||||||
@ -45,6 +44,7 @@ type
|
|||||||
FHeaderStream: TStream;
|
FHeaderStream: TStream;
|
||||||
FIncludePaths: TStrings;
|
FIncludePaths: TStrings;
|
||||||
FInputFile: String;
|
FInputFile: String;
|
||||||
|
FOnUnitAliasData: Pointer;
|
||||||
FOnWrite: TWriteEvent;
|
FOnWrite: TWriteEvent;
|
||||||
FOnWriteCallBack: TWriteCallBack;
|
FOnWriteCallBack: TWriteCallBack;
|
||||||
FOutputFile: String;
|
FOutputFile: String;
|
||||||
@ -60,10 +60,12 @@ type
|
|||||||
FCallBackData : Pointer;
|
FCallBackData : Pointer;
|
||||||
FLastErrorClass : String;
|
FLastErrorClass : String;
|
||||||
FLastError : String;
|
FLastError : String;
|
||||||
|
FOnUnitAlias : TUnitAliasCallBack;
|
||||||
procedure SetDefines(AValue: TStrings);
|
procedure SetDefines(AValue: TStrings);
|
||||||
procedure SetIncludePaths(AValue: TStrings);
|
procedure SetIncludePaths(AValue: TStrings);
|
||||||
procedure SetOnWrite(AValue: TWriteEvent);
|
procedure SetOnWrite(AValue: TWriteEvent);
|
||||||
procedure SetWriteCallback(AValue: TWriteCallBack);
|
procedure SetWriteCallback(AValue: TWriteCallBack);
|
||||||
|
function CheckUnitAlias(const AUnitName: String): String;
|
||||||
Protected
|
Protected
|
||||||
procedure DoExecute;virtual;
|
procedure DoExecute;virtual;
|
||||||
Procedure DoWriteEvent; virtual;
|
Procedure DoWriteEvent; virtual;
|
||||||
@ -81,9 +83,11 @@ type
|
|||||||
// OutputStream can be used combined with write callbacks.
|
// OutputStream can be used combined with write callbacks.
|
||||||
Property OutputStream : TStream Read FOutputStream Write FOutputStream;
|
Property OutputStream : TStream Read FOutputStream Write FOutputStream;
|
||||||
Property HeaderStream : TStream Read FHeaderStream Write FHeaderStream;
|
Property HeaderStream : TStream Read FHeaderStream Write FHeaderStream;
|
||||||
|
Property OnUnitAlias: TUnitAliasCallBack read FOnUnitAlias Write FOnUnitAlias;
|
||||||
|
Property OnUnitAliasData : Pointer Read FOnUnitAliasData Write FOnUnitAliasData;
|
||||||
Property OnWriteCallBack : TWriteCallBack Read FOnWriteCallBack Write SetWriteCallback;
|
Property OnWriteCallBack : TWriteCallBack Read FOnWriteCallBack Write SetWriteCallback;
|
||||||
Property CallbackData : Pointer Read FCallBackData Write FCallBackData;
|
Property CallbackData : Pointer Read FCallBackData Write FCallBackData;
|
||||||
|
Property ExtraUnits : String Read FExtraUnits write FExtraUnits;
|
||||||
Published
|
Published
|
||||||
Property Defines : TStrings Read FDefines Write SetDefines;
|
Property Defines : TStrings Read FDefines Write SetDefines;
|
||||||
Property ConfigFileName : String Read FConfigFile Write FConfigFile;
|
Property ConfigFileName : String Read FConfigFile Write FConfigFile;
|
||||||
@ -97,6 +101,8 @@ type
|
|||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
|
||||||
|
uses Math;
|
||||||
|
|
||||||
ResourceString
|
ResourceString
|
||||||
SErrNoDestGiven = 'No destination file specified.';
|
SErrNoDestGiven = 'No destination file specified.';
|
||||||
SErrNoSourceParsed = 'Parsing produced no file.';
|
SErrNoSourceParsed = 'Parsing produced no file.';
|
||||||
@ -131,6 +137,23 @@ begin
|
|||||||
FWriteStream:=TStringStream.Create('');
|
FWriteStream:=TStringStream.Create('');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TStubCreator.CheckUnitAlias(const AUnitName: String): String;
|
||||||
|
const
|
||||||
|
MAX_UNIT_NAME_LENGTH = 255;
|
||||||
|
|
||||||
|
var
|
||||||
|
UnitMaxLenthName: Integer;
|
||||||
|
|
||||||
|
begin
|
||||||
|
Result := AUnitName;
|
||||||
|
UnitMaxLenthName := Max(MAX_UNIT_NAME_LENGTH, Result.Length);
|
||||||
|
|
||||||
|
SetLength(Result, UnitMaxLenthName);
|
||||||
|
|
||||||
|
if FOnUnitAlias(OnUnitAliasData, @Result[1], UnitMaxLenthName) then
|
||||||
|
Result := LeftStr(PChar(Result), UnitMaxLenthName);
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TStubCreator.DoWriteEvent;
|
procedure TStubCreator.DoWriteEvent;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
@ -279,7 +302,7 @@ end;
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
Function TStubCreator.GetModule : TPasModule;
|
function TStubCreator.GetModule: TPasModule;
|
||||||
|
|
||||||
Var
|
Var
|
||||||
SE : TSimpleEngine;
|
SE : TSimpleEngine;
|
||||||
@ -327,7 +350,8 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TStubCreator.MaybeGetFileStream(AStream: TStream; const AFileName: String; AfileMode : Word) : TStream;
|
function TStubCreator.MaybeGetFileStream(AStream: TStream;
|
||||||
|
const AFileName: String; aFileMode: Word): TStream;
|
||||||
begin
|
begin
|
||||||
If Assigned(AStream) then
|
If Assigned(AStream) then
|
||||||
Result:=AStream
|
Result:=AStream
|
||||||
@ -359,12 +383,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure TStubCreator.WriteModule(M : TPAsModule);
|
procedure TStubCreator.WriteModule(M: TPasModule);
|
||||||
|
|
||||||
Var
|
Var
|
||||||
F,H : TStream;
|
F,H : TStream;
|
||||||
W : TPasWriter;
|
W : TPasWriter;
|
||||||
U : String;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
W:=Nil;
|
W:=Nil;
|
||||||
@ -385,14 +408,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
W:=TPasWriter.Create(F);
|
W:=TPasWriter.Create(F);
|
||||||
W.Options:=FOptions;
|
W.Options:=FOptions;
|
||||||
U:=FExtraUnits;
|
W.ExtraUnits:=FExtraUnits;
|
||||||
if Pos(LowerCase(DTypesUnit),LowerCase(U)) = 0 then
|
|
||||||
begin
|
if Assigned(FOnUnitAlias) then
|
||||||
if (U<>'') then
|
W.OnUnitAlias:=@CheckUnitAlias;
|
||||||
U:=','+U;
|
|
||||||
U:=DTypesUnit+U;
|
|
||||||
end;
|
|
||||||
W.ExtraUnits:=U;
|
|
||||||
if FIndentSize<>-1 then
|
if FIndentSize<>-1 then
|
||||||
W.IndentSize:=FIndentSize;
|
W.IndentSize:=FIndentSize;
|
||||||
if FLineNumberWidth>0 then
|
if FLineNumberWidth>0 then
|
||||||
|
Loading…
Reference in New Issue
Block a user