From 7ae830ae7e9c7c00f3dab4af01cbd45d5a03bf33 Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Wed, 15 Sep 2021 22:22:16 -0500 Subject: [PATCH] Initial support for compound literals. Compound literals outside of functions should work at this point. Compound literals inside of functions are not fully implemented, so they are disabled for now. (There is some code to support them, but the code to actually initialize them at the appropriate time is not written yet.) --- CCommon.pas | 9 ++++---- Expression.pas | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ Parser.pas | 57 +++++++++++++++++++++++++++++++++++++++++++++++++- Scanner.pas | 1 + 4 files changed, 117 insertions(+), 5 deletions(-) diff --git a/CCommon.pas b/CCommon.pas index bff3a37..327f890 100644 --- a/CCommon.pas +++ b/CCommon.pas @@ -360,10 +360,11 @@ type isForwardDeclared: boolean; {does this var use a forward declared type?} class: tokenEnum; {storage class} case storage: storageType of - stackFrame: (lln: integer); {local label #} - parameter: (pln: integer; {paramater label #} - pdisp: integer; {disp of parameter} - pnext: identPtr); {next parameter} + stackFrame: (lln: integer; {local label #} + clnext: identPtr); {next compound literal} + parameter: (pln: integer; {paramater label #} + pdisp: integer; {disp of parameter} + pnext: identPtr); {next parameter} external: (); global,private: (); none: (); diff --git a/Expression.pas b/Expression.pas index 8165d05..99dee3b 100644 --- a/Expression.pas +++ b/Expression.pas @@ -268,6 +268,14 @@ function MakeFuncIdentifier: identPtr; extern; { } { This must only be called within a function body. } + +function MakeCompoundLiteral(tp: typePtr): identPtr; extern; + +{ Make the identifier for a compound literal. } +{ } +{ parameters: } +{ tp - the type of the compound literal } + {-- External unsigned math routines ----------------------------} function lshr (x,y: longint): longint; extern; @@ -2001,6 +2009,49 @@ var end; {DoGeneric} + procedure DoCompoundLiteral; + + { process a compound literal expression } + + label 1; + + var + id: identPtr; + sp: tokenPtr; + + begin {DoCompoundLiteral} + if kind in [preprocessorExpression,arrayExpression] then begin + op := opStack; + while op <> nil do begin + if op^.token.kind = sizeofsy then + goto 1; + op := op^.next; + end; {while} + Error(41); + errorFound := true; + end; {if} +1: + id := MakeCompoundLiteral(opStack^.castType); + opStack := opStack^.next; + + {create an operand on the stack} + new(sp); + sp^.token.kind := ident; + sp^.token.class := identifier; + sp^.token.symbolPtr := id; + sp^.token.name := id^.name; + sp^.id := id; + sp^.next := stack; + sp^.left := nil; + sp^.middle := nil; + sp^.right := nil; + stack := sp; + + ComplexTerm; + expectingTerm := false; + end; {DoCompoundLiteral} + + begin {ExpressionTree} opStack := nil; stack := nil; @@ -2147,6 +2198,10 @@ if token.kind in startExpression then begin parenCount := parenCount+1; end; end {else if} + else if (token.kind = lbracech) {handle a compound literal} + and (opstack <> nil) and (opStack^.token.kind = castoper) then begin + DoCompoundLiteral + end {else if} else if token.kind = _Genericsy then {handle _Generic} DoGeneric else begin {handle an operation...} diff --git a/Parser.pas b/Parser.pas index 89fd450..d7a8b27 100644 --- a/Parser.pas +++ b/Parser.pas @@ -69,6 +69,14 @@ function MakeFuncIdentifier: identPtr; { This must only be called within a function body. } +function MakeCompoundLiteral(tp: typePtr): identPtr; + +{ Make the identifier for a compound literal. } +{ } +{ parameters: } +{ tp - the type of the compound literal } + + procedure InitParser; { Initialize the parser } @@ -176,6 +184,8 @@ var statementList: statementPtr; {list of open statements} savedVolatile: boolean; {saved copy of volatile} doingForLoopClause1: boolean; {doing the first clause of a for loop?} + compoundLiteralNumber: integer; {number of compound literal} + compoundLiteralToAllocate: identPtr; {compound literal that needs space allocated} {parameter processing variables} {------------------------------} @@ -325,6 +335,11 @@ var stPtr: statementPtr; {work pointer} begin {EndCompoundStatement} +while compoundLiteralToAllocate <> nil do begin {allocate compound literals} + Gen2(dc_loc, compoundLiteralToAllocate^.lln, + long(compoundLiteralToAllocate^.itype^.size).lsw); + compoundLiteralToAllocate := compoundLiteralToAllocate^.clnext; + end {while}; dumpLocal := false; stPtr := statementList; {pop the statement record} statementList := stPtr^.next; @@ -4093,7 +4108,7 @@ begin {TypeName} DeclarationSpecifiers(specifierQualifierListElement, rparench); {_Alignas is not allowed in most uses of type names. } -{It would be allowed in compound literals, if we supported them.} +{TODO: _Alignas should be allowed in compound literals. } if _Alignassy in declarationModifiers then Error(142); @@ -4534,6 +4549,44 @@ MakeFuncIdentifier := id; end; {MakeFuncIdentifier} +function MakeCompoundLiteral{tp: typePtr): identPtr}; + +{ Make the identifier for a compound literal. } +{ } +{ parameters: } +{ tp - the type of the compound literal } + +type + nameString = packed array [0..24] of char; + +var + id: identPtr; {the identifier for the literal} + name: ^nameString; {the name for the identifier} + class: tokenEnum; {storage class} + +begin {MakeCompoundLiteral} +if functionTable <> nil then begin + Error(164); + class := autosy + end {if} +else + class := staticsy; +name := pointer(Malloc(25)); +name^ := concat('~CompoundLiteral', cnvis(compoundLiteralNumber)); +id := NewSymbol(name, tp, class, variableSpace, defined); +Initializer(id); +MakeCompoundLiteral := id; +compoundLiteralNumber := compoundLiteralNumber + 1; +if compoundLiteralNumber = 0 then + Error(57); +if class = autosy then begin + id^.lln := GetLocalLabel; + id^.clnext := compoundLiteralToAllocate; + compoundLiteralToAllocate := id; + end; +end; {MakeFuncIdentifier} + + procedure InitParser; { Initialize the parser } @@ -4554,6 +4607,8 @@ statementList := nil; {no open statements} codegenStarted := false; {code generator is not started} doingForLoopClause1 := false; {not doing a for loop} fIsNoreturn := false; {not doing a noreturn function} +compoundLiteralNumber := 1; {no compound literals yet} +compoundLiteralToAllocate := nil; {no compound literals needing space yet} {init syntactic classes of tokens} {See C17 section 6.7 ff.} diff --git a/Scanner.pas b/Scanner.pas index b874d05..b9d957d 100644 --- a/Scanner.pas +++ b/Scanner.pas @@ -720,6 +720,7 @@ if list or (numErr <> 0) then begin 161: msg := @'illegal operator in a constant expression'; 162: msg := @'invalid escape sequence'; 163: msg := @'pointer assignment discards qualifier(s)'; + 164: msg := @'compound literals within functions are not supported by ORCA/C'; otherwise: Error(57); end; {case} writeln(msg^);