mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-13 07:59:09 +02:00
+ support for packed array constants
git-svn-id: trunk@6583 -
This commit is contained in:
parent
42da0e5688
commit
3794fab64d
2
.gitattributes
vendored
2
.gitattributes
vendored
@ -6791,6 +6791,8 @@ tests/test/tparray1.pp svneol=native#text/plain
|
|||||||
tests/test/tparray10.pp svneol=native#text/plain
|
tests/test/tparray10.pp svneol=native#text/plain
|
||||||
tests/test/tparray11.pp svneol=native#text/plain
|
tests/test/tparray11.pp svneol=native#text/plain
|
||||||
tests/test/tparray12.pp svneol=native#text/plain
|
tests/test/tparray12.pp svneol=native#text/plain
|
||||||
|
tests/test/tparray13.pp svneol=native#text/plain
|
||||||
|
tests/test/tparray14.pp svneol=native#text/plain
|
||||||
tests/test/tparray2.pp svneol=native#text/plain
|
tests/test/tparray2.pp svneol=native#text/plain
|
||||||
tests/test/tparray3.pp svneol=native#text/plain
|
tests/test/tparray3.pp svneol=native#text/plain
|
||||||
tests/test/tparray4.pp svneol=native#text/plain
|
tests/test/tparray4.pp svneol=native#text/plain
|
||||||
|
@ -49,6 +49,46 @@ implementation
|
|||||||
|
|
||||||
{$maxfpuregisters 0}
|
{$maxfpuregisters 0}
|
||||||
|
|
||||||
|
{ bitpacks "value" as bitpacked value of bitsize "packedbitsize" and }
|
||||||
|
{ loadsize "loadbitsize" into "curval", which has already been filled up }
|
||||||
|
{ to "curbitoffset", and stores the spillover if any into "nextval". }
|
||||||
|
{ It also updates curbitoffset to reflect how many bits of currval are }
|
||||||
|
{ now used (can be > packedbitsize in case of spillover) }
|
||||||
|
procedure bitpackval(value: aword; var curval: aword; out nextval: aword; loadbitsize, packedbitsize: byte; var curbitoffset: smallint);
|
||||||
|
var
|
||||||
|
tmpval: aword;
|
||||||
|
shiftcount: longint;
|
||||||
|
begin
|
||||||
|
{ 1 shl 32/64 = 1 on i386/x86_64 }
|
||||||
|
if (loadbitsize<>AintBits) then
|
||||||
|
tmpval:=(aword(1) shl loadbitsize) - 1
|
||||||
|
else
|
||||||
|
tmpval:=aword(-1);
|
||||||
|
if (target_info.endian=endian_big) then
|
||||||
|
begin
|
||||||
|
{ bitpacked format: left-aligned (i.e., "big endian bitness") }
|
||||||
|
curval:=curval or (((value shl (loadbitsize-packedbitsize)) shr curbitoffset) and tmpval);
|
||||||
|
shiftcount:=((loadbitsize-packedbitsize)-curbitoffset);
|
||||||
|
{ carry-over to the next element? }
|
||||||
|
if (shiftcount<0) then
|
||||||
|
nextval:=(value and ((aword(1) shl (-shiftcount))-1)) shl
|
||||||
|
(loadbitsize+shiftcount)
|
||||||
|
else
|
||||||
|
nextval:=0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
{ bitpacked format: right aligned (i.e., "little endian bitness") }
|
||||||
|
curval:=curval or ((value shl curbitoffset) and tmpval);
|
||||||
|
{ carry-over to the next element? }
|
||||||
|
if (curbitoffset+packedbitsize>loadbitsize) then
|
||||||
|
nextval:=value shr (loadbitsize-curbitoffset)
|
||||||
|
else
|
||||||
|
nextval:=0;
|
||||||
|
end;
|
||||||
|
inc(curbitoffset,packedbitsize);
|
||||||
|
end;
|
||||||
|
|
||||||
{ this procedure reads typed constants }
|
{ this procedure reads typed constants }
|
||||||
procedure read_typed_const_data(list:tasmlist;def:tdef);
|
procedure read_typed_const_data(list:tasmlist;def:tdef);
|
||||||
|
|
||||||
@ -608,6 +648,96 @@ implementation
|
|||||||
n.free;
|
n.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure flush_packed_value(list: tasmlist; var curval, nextval: aword; loadbitsize: byte; var curbitoffset: smallint);
|
||||||
|
begin
|
||||||
|
{ these values have to be byte swapped when cross-compiling }
|
||||||
|
{ from one endianess to another, but this will be done }
|
||||||
|
{ automatically by the assembler writer }
|
||||||
|
case loadbitsize of
|
||||||
|
8: list.concat(tai_const.create_8bit(curval));
|
||||||
|
16: list.concat(tai_const.create_16bit(curval));
|
||||||
|
32: list.concat(tai_const.create_32bit(curval));
|
||||||
|
64: list.concat(tai_const.create_64bit(curval));
|
||||||
|
else
|
||||||
|
internalerror(2007022011);
|
||||||
|
end;
|
||||||
|
curval:=nextval;
|
||||||
|
nextval:=0;
|
||||||
|
dec(curbitoffset,loadbitsize);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ parse a single constant and add it to the packed const info }
|
||||||
|
{ represented by curval etc (see explanation of bitpackval for }
|
||||||
|
{ what the different parameters mean) }
|
||||||
|
function parse_single_packed_const(list: tasmlist; def: tdef; var curval: aword; out nextval: aword; loadbitsize, packedbitsize: byte; var curbitoffset: smallint): boolean;
|
||||||
|
var
|
||||||
|
n : tnode;
|
||||||
|
begin
|
||||||
|
result:=true;
|
||||||
|
n:=comp_expr(true);
|
||||||
|
if (n.nodetype <> ordconstn) or
|
||||||
|
not equal_defs(n.resultdef,def) and
|
||||||
|
not is_subequal(n.resultdef,def) then
|
||||||
|
begin
|
||||||
|
n.free;
|
||||||
|
incompatibletypes(n.resultdef,def);
|
||||||
|
consume_all_until(_SEMICOLON);
|
||||||
|
result:=false;
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
bitpackval(tordconstnode(n).value,curval,nextval,loadbitsize,packedbitsize,curbitoffset);
|
||||||
|
if (curbitoffset>=loadbitsize) then
|
||||||
|
flush_packed_value(list,curval,nextval,loadbitsize,curbitoffset);
|
||||||
|
n.free;
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
{ parses a packed array constant }
|
||||||
|
procedure parse_packed_array_def(list: tasmlist; def: tarraydef);
|
||||||
|
var
|
||||||
|
i : aint;
|
||||||
|
loadmask: aword;
|
||||||
|
curval, nextval: aword;
|
||||||
|
curbitoffset: smallint;
|
||||||
|
packedbitsize,
|
||||||
|
loadbitsize: byte;
|
||||||
|
begin
|
||||||
|
if not(def.elementdef.typ in [orddef,enumdef]) then
|
||||||
|
internalerror(2007022010);
|
||||||
|
{ begin of the array }
|
||||||
|
consume(_LKLAMMER);
|
||||||
|
packedbitsize:=def.elepackedbitsize;
|
||||||
|
loadbitsize:=packedbitsloadsize(packedbitsize)*8;
|
||||||
|
{ 1 shl 32/64 = 1 on i386/x86_64 }
|
||||||
|
if (loadbitsize*8 <> sizeof(aword)) then
|
||||||
|
loadmask:=aword(1) shl loadbitsize
|
||||||
|
else
|
||||||
|
loadmask:=aword(-1);
|
||||||
|
curval:=0;
|
||||||
|
curbitoffset:=0;
|
||||||
|
i:=def.lowrange;
|
||||||
|
{ can't use for-loop, fails when cross-compiling from }
|
||||||
|
{ 32 to 64 bit because i is then 64 bit }
|
||||||
|
while (i<def.highrange) do
|
||||||
|
begin
|
||||||
|
{ get next item of the packed array }
|
||||||
|
if not parse_single_packed_const(list,def.elementdef,curval,nextval,loadbitsize,packedbitsize,curbitoffset) then
|
||||||
|
exit;
|
||||||
|
consume(_COMMA);
|
||||||
|
inc(i);
|
||||||
|
end;
|
||||||
|
{ final item }
|
||||||
|
if not parse_single_packed_const(list,def.elementdef,curval,nextval,loadbitsize,packedbitsize,curbitoffset) then
|
||||||
|
exit;
|
||||||
|
{ flush final incomplete value if necessary }
|
||||||
|
if (curbitoffset <> 0) then
|
||||||
|
flush_packed_value(list,curval,nextval,loadbitsize,curbitoffset);
|
||||||
|
consume(_RKLAMMER);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
procedure parse_arraydef(list:tasmlist;def:tarraydef);
|
procedure parse_arraydef(list:tasmlist;def:tarraydef);
|
||||||
var
|
var
|
||||||
n : tnode;
|
n : tnode;
|
||||||
@ -623,11 +753,11 @@ implementation
|
|||||||
consume(_NIL);
|
consume(_NIL);
|
||||||
list.concat(Tai_const.Create_sym(nil));
|
list.concat(Tai_const.Create_sym(nil));
|
||||||
end
|
end
|
||||||
{ no packed array constants supported }
|
{ packed array constant }
|
||||||
else if is_packed_array(def) then
|
else if is_packed_array(def) and
|
||||||
|
(def.elepackedbitsize mod 8 <> 0) then
|
||||||
begin
|
begin
|
||||||
Message(type_e_no_const_packed_array);
|
parse_packed_array_def(list,def);
|
||||||
consume_all_until(_RKLAMMER);
|
|
||||||
end
|
end
|
||||||
{ normal array const between brackets }
|
{ normal array const between brackets }
|
||||||
else if try_to_consume(_LKLAMMER) then
|
else if try_to_consume(_LKLAMMER) then
|
||||||
|
120
tests/test/tparray13.pp
Normal file
120
tests/test/tparray13.pp
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
{$mode macpas}
|
||||||
|
|
||||||
|
{$r-}
|
||||||
|
|
||||||
|
procedure error(l: longint);
|
||||||
|
begin
|
||||||
|
writeln('error near ',l);
|
||||||
|
halt(1);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test8bit;
|
||||||
|
type
|
||||||
|
ta = 0..1;
|
||||||
|
const
|
||||||
|
b: packed array[0..9] of ta = (1,0,1,1,1,0,1,1,1,0);
|
||||||
|
results: array[0..9] of ta = (1,0,1,1,1,0,1,1,1,0);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>2) then
|
||||||
|
error(1);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(7);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test8to16bit;
|
||||||
|
type
|
||||||
|
ta = 0..7;
|
||||||
|
const
|
||||||
|
b: packed array[0..5] of ta = (2,4,1,7,5,1);
|
||||||
|
results: array[0..5] of ta = (2,4,1,7,5,1);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>3) then
|
||||||
|
error(16);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(17);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test16bit;
|
||||||
|
type
|
||||||
|
ta = 0..511;
|
||||||
|
const
|
||||||
|
b: packed array[0..4] of ta = (356,39,485,100,500);
|
||||||
|
results: array[0..4] of ta = (356,39,485,100,500);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>6) then
|
||||||
|
error(26);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(27);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test16to24bit;
|
||||||
|
type
|
||||||
|
ta = 0..2047;
|
||||||
|
const
|
||||||
|
b: packed array[0..4] of ta = (1000,67,853,512,759);
|
||||||
|
results: array[0..4] of ta = (1000,67,853,512,759);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>7) then
|
||||||
|
error(36);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(37);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test32bit;
|
||||||
|
type
|
||||||
|
ta = 0..(1 shl 19) - 1;
|
||||||
|
const
|
||||||
|
b: packed array[0..4] of ta = ($0002F687,$00032222,$000178EE,$000057970,$0007E1D2);
|
||||||
|
results: array[0..4] of ta = ($0002F687,$00032222,$000178EE,$000057970,$0007E1D2);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>12) then
|
||||||
|
error(46);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(47);
|
||||||
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
procedure test32to40bit;
|
||||||
|
type
|
||||||
|
ta = 0..$7fffffff;
|
||||||
|
const
|
||||||
|
b: packed array[0..4] of ta = ($71567851,$56789ABD,$50F11178,$39D68DDC,$6C7A5A7);
|
||||||
|
results: array[0..4] of ta = ($71567851,$56789ABD,$50F11178,$39D68DDC,$6C7A5A7);
|
||||||
|
var
|
||||||
|
i: longint;
|
||||||
|
begin
|
||||||
|
if (sizeof(b)<>20) then
|
||||||
|
error(56);
|
||||||
|
for i := low(results) to high(results) do
|
||||||
|
if b[i] <> results[i] then
|
||||||
|
error(57);
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
test8bit;
|
||||||
|
test8to16bit;
|
||||||
|
test16bit;
|
||||||
|
test16to24bit;
|
||||||
|
test32bit;
|
||||||
|
test32to40bit;
|
||||||
|
end.
|
65
tests/test/tparray14.pp
Normal file
65
tests/test/tparray14.pp
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
{ based on gpc test pvs1 }
|
||||||
|
{ FLAG --extended-pascal }
|
||||||
|
|
||||||
|
{TEST 6.6.5.4-1, CLASS=CONFORMANCE}
|
||||||
|
|
||||||
|
{ This program tests that pack and unpack are
|
||||||
|
implemented in this compiler as according to the
|
||||||
|
Standard.
|
||||||
|
The compiler fails if the program does not compile. }
|
||||||
|
|
||||||
|
program t6p6p5p4d1(output);
|
||||||
|
|
||||||
|
{$mode macpas}
|
||||||
|
|
||||||
|
type
|
||||||
|
colourtype = (red,pink,orange,yellow,green,blue);
|
||||||
|
|
||||||
|
var
|
||||||
|
unone : array[3..24] of char;
|
||||||
|
pacy : array[1..4] of char;
|
||||||
|
pactwo : packed array[6..7] of colourtype;
|
||||||
|
i : integer;
|
||||||
|
colour : colourtype;
|
||||||
|
s: string;
|
||||||
|
|
||||||
|
const
|
||||||
|
pacone : packed array[1..4] of char = 'ABCD';
|
||||||
|
untwo : array[4..8] of colourtype = (red,pink,orange,yellow,green);
|
||||||
|
begin
|
||||||
|
pacy:=pacone;
|
||||||
|
if pacy <> 'ABCD' then
|
||||||
|
halt(1);
|
||||||
|
s := pacone;
|
||||||
|
unpack(pacone,unone,5);
|
||||||
|
if (unone[3] <> #0) or
|
||||||
|
(unone[4] <> #0) or
|
||||||
|
(unone[5] <> 'A') or
|
||||||
|
(unone[6] <> 'B') or
|
||||||
|
(unone[7] <> 'C') or
|
||||||
|
(unone[8] <> 'D') or
|
||||||
|
(unone[9] <> #0) or
|
||||||
|
(unone[10] <> #0) or
|
||||||
|
(unone[11] <> #0) then
|
||||||
|
halt(1);
|
||||||
|
colour:=red;
|
||||||
|
for i:=4 to 8 do
|
||||||
|
begin
|
||||||
|
if (untwo[i]<>colour) then
|
||||||
|
halt(2);
|
||||||
|
colour:=succ(colour)
|
||||||
|
end;
|
||||||
|
pack(untwo,5,pactwo);
|
||||||
|
if (pactwo[6] <> pink) or
|
||||||
|
(pactwo[7] <> orange) then
|
||||||
|
halt(1);
|
||||||
|
writeln('unone[5] = ''', unone[5], ''' = ', ord(unone[5]));
|
||||||
|
if unone[5]='A' then
|
||||||
|
writeln(' PASS...6.6.5.4-1')
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
writeln(' FAIL...6.6.5.4-1');
|
||||||
|
halt(1);
|
||||||
|
end;
|
||||||
|
end.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user