Skip to content

Commit

Permalink
feat: add prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
Mati365 committed Dec 30, 2023
1 parent f03f75f commit 5ad4695
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -230,15 +230,14 @@ export class X86StdcallFnCaller implements X86ConventionalFnCaller {
};
}

private getReturnReg({ context, declInstruction }: X86FnBasicCompilerAttrs) {
const regs = context.allocator.regs.ownership.getAvailableRegs();
private getReturnReg({ declInstruction }: X86FnBasicCompilerAttrs) {
const { returnType } = declInstruction;

if (!returnType || returnType.isVoid()) {
return null;
}

return regs.general.list[0];
return returnType.getByteSize() === 1 ? 'al' : 'ax';
}

private preserveConventionRegsAsm({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export function compileArrayInitializerDefAsm({

// [1, 2, "as", 3] -> [[1, 2], "as", [3]]
const groupedDefs = initializer.fields.reduce(
({ prevFieldType, groups }, field) => {
({ prevFieldType, groups }, { value: field }) => {
const currentFieldType = typeof field;

if (currentFieldType !== prevFieldType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,9 @@ export class X86BasicRegAllocator {

if (
!castToPointerIfArray(arg.type).isScalar() &&
(!isUnionLikeType(arg.type) ||
!isStructLikeType(arg.type) ||
!arg.type.canBeStoredInReg())
!isUnionLikeType(arg.type) &&
!isStructLikeType(arg.type) &&
!arg.type.canBeStoredInReg()
) {
throw new CBackendError(CBackendErrorCode.REG_ALLOCATOR_ERROR);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { isNil } from 'ramda';
import { isTreeNode } from '@ts-c-compiler/grammar';

import { CVariableInitializerVisitor } from './CVariableInitializerVisitor';
import {
CVariableInitializerTree,
CVariableInitializePair,
CVariableInitializeValue,
isInitializerTreeValue,
CVariableInitializerTree,
isInitializerValuePair,
} from '../../scope/variables/CVariableInitializerTree';

/**
Expand All @@ -17,23 +19,36 @@ export class CVariableInitializerPrintVisitor extends CVariableInitializerVisito
return this._reduced;
}

override enter(value: CVariableInitializeValue) {
override enter(
maybePair: CVariableInitializePair | CVariableInitializerTree,
) {
if (this._reduced && this._reduced[this._reduced.length - 2] !== '{') {
this._reduced += ', ';
}

let serializedValue = value;
if (isInitializerTreeValue(value)) {
let serializedValue: CVariableInitializeValue = '';

if (isTreeNode(maybePair)) {
serializedValue = '{ ';
} else if (isTreeNode(value)) {
serializedValue = '<expr>';
} else if (isInitializerValuePair(maybePair)) {
if (isTreeNode(maybePair.value)) {
serializedValue = '<expr>';
} else {
serializedValue = maybePair.value;
}
} else if (isNil(maybePair)) {
serializedValue = 'null';
}

this._reduced += serializedValue;
if (serializedValue) {
this._reduced += serializedValue;
}
}

override leave(value: CVariableInitializeValue) {
if (isInitializerTreeValue(value)) {
override leave(
maybePair: CVariableInitializePair | CVariableInitializerTree,
) {
if (isTreeNode(maybePair)) {
this._reduced += ' }';
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
import { isCompilerTreeNode } from 'frontend/parser';

import { AbstractTreeVisitor } from '@ts-c-compiler/grammar';
import { CVariableInitializeValue } from '../../scope/variables';
import {
CVariableInitializePair,
CVariableInitializerTree,
} from '../../scope/variables';

export class CVariableInitializerVisitor extends AbstractTreeVisitor<CVariableInitializeValue> {
shouldVisitNode(node: CVariableInitializeValue): boolean {
export class CVariableInitializerVisitor extends AbstractTreeVisitor<
CVariableInitializePair | CVariableInitializerTree
> {
shouldVisitNode(
node: CVariableInitializePair | CVariableInitializerTree,
): boolean {
return !isCompilerTreeNode(node);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {

import {
CVariableInitializerTree,
CVariableInitializeValue,
CVariableInitializePair,
} from '../../../scope/variables';

import {
Expand Down Expand Up @@ -87,7 +87,7 @@ export class CTypeInitializerBuilderVisitor extends CInnerTypeTreeVisitor {

if (!this.tree) {
this.tree = new CVariableInitializerTree(baseType, node);
this.maxSize = this.tree.scalarValuesCount;
this.maxSize = this.tree.c89initializerFieldsCount;
}

const arrayType = isArrayLikeType(baseType);
Expand Down Expand Up @@ -223,15 +223,20 @@ export class CTypeInitializerBuilderVisitor extends CInnerTypeTreeVisitor {
}
}

this.appendNextOffsetValue(exprValue, noSizeCheck);
} else if (isCompilerTreeNode(exprValue)) {
this.appendNextOffsetValue(
this.parseTreeNodeExpressionValue(node, expectedType, exprValue),
{ type: expectedType, value: exprValue },
noSizeCheck,
);
} else if (isCompilerTreeNode(exprValue)) {
this.appendNextOffsetValue({
type: expectedType,
value: this.parseTreeNodeExpressionValue(node, expectedType, exprValue),
});
} else {
this.appendNextOffsetValue(
this.parseScalarValue(node, expectedType, exprValue),
);
this.appendNextOffsetValue({
type: expectedType,
value: this.parseScalarValue(node, expectedType, exprValue),
});
}
}

Expand Down Expand Up @@ -311,7 +316,7 @@ export class CTypeInitializerBuilderVisitor extends CInnerTypeTreeVisitor {
offset +=
+constExprResult.right *
dimensions.reduce((acc, num, index) => (index ? acc * num : 1), 1) *
type.scalarValuesCount;
type.c89initializerFieldsCount;
}
}

Expand Down Expand Up @@ -424,13 +429,13 @@ export class CTypeInitializerBuilderVisitor extends CInnerTypeTreeVisitor {
* Appends next value to tree and increments currentKey if number
*/
private appendNextOffsetValue(
entryValue: CVariableInitializeValue,
entryValue: CVariableInitializePair,
noSizeCheck?: boolean,
) {
const { tree, maxSize, baseType } = this;
// handle struct Vec2 vec[] = { of_vector(), of_vector() }; initializers
const delta = isCompilerTreeNode(entryValue)
? entryValue.type.scalarValuesCount
? entryValue.type.c89initializerFieldsCount
: 1;

if (isStructLikeType(baseType) || isUnionLikeType(baseType)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,12 @@ export type CVariableInitializeValue =
| CVariableInitializerTree
| ASTCCompilerNode;

export type CVariableInitializerFields = CVariableInitializeValue[];
export type CVariableInitializePair = {
type: CType;
value: CVariableInitializeValue;
};

export type CVariableInitializerFields = CVariableInitializePair[];

export function isConstantVariableInitializer(value: CVariableInitializeValue) {
if (!value) {
Expand All @@ -36,6 +41,12 @@ export function isInitializerTreeValue(
return R.is(Object, value) && R.has('_baseType', value);
}

export function isInitializerValuePair(
pair: any,
): pair is CVariableInitializePair {
return !!pair && 'type' in pair && 'value' in pair;
}

type CVariableByteInitializerAttrs<C> = {
baseType: CType;
parentAST?: C;
Expand Down Expand Up @@ -83,16 +94,18 @@ export class CVariableInitializerTree<
return new CVariableInitializerTree(baseType, parentAST, fields);
}

fill(value: CVariableInitializeValue) {
this._fields = new Array(this.scalarValuesCount).fill(value);
fill(value: CVariableInitializePair) {
this._fields = new Array(this.c89initializerFieldsCount).fill(value);
}

walk(visitor: AbstractTreeVisitor<any>): void {
this._fields.forEach(visitor.visit.bind(visitor));
}

hasOnlyConstantExpressions() {
return this._fields.every(isConstantVariableInitializer);
return this._fields.every(item =>
isConstantVariableInitializer(item.value),
);
}

getSingleItemByteSize() {
Expand Down Expand Up @@ -130,7 +143,7 @@ export class CVariableInitializerTree<
/**
* Sets values on given offset and if offset is bigger than array fills with null
*/
setAndExpand(offset: number, value: CVariableInitializeValue) {
setAndExpand(offset: number, value: CVariableInitializePair) {
const { fields } = this;

this.ensureSize(offset);
Expand All @@ -140,7 +153,7 @@ export class CVariableInitializerTree<
/**
* Used to return value for non-array type initializers
*/
getFirstValue(): CVariableInitializeValue {
getFirstValue(): CVariableInitializePair {
return this._fields[0];
}

Expand Down Expand Up @@ -177,7 +190,7 @@ export class CVariableInitializerTree<
return baseType.ofSize(
Math.ceil(
this.getFlattenNonLiteralScalarFieldsCount() /
baseType.baseType.scalarValuesCount,
baseType.baseType.c89initializerFieldsCount,
),
);
}
Expand All @@ -192,7 +205,7 @@ export class CVariableInitializerTree<
const { baseType } = this;

if (isStructLikeType(baseType) || isUnionLikeType(baseType)) {
return baseType.getFieldTypeByIndex(
return baseType.getFieldTypeByC89InitializerIndex(
offset % baseType.getFlattenFieldsCount(),
);
}
Expand All @@ -201,7 +214,7 @@ export class CVariableInitializerTree<
const baseArrayType = baseType.getSourceType();

if (isStructLikeType(baseArrayType) || isUnionLikeType(baseArrayType)) {
return baseArrayType.getFieldTypeByIndex(
return baseArrayType.getFieldTypeByC89InitializerIndex(
offset % baseArrayType.getFlattenFieldsCount(),
);
}
Expand Down Expand Up @@ -235,7 +248,7 @@ export class CVariableInitializerTree<
* @example
* int abc[3][4] => 12
*/
get scalarValuesCount(): number {
return this.baseType.scalarValuesCount;
get c89initializerFieldsCount(): number {
return this.baseType.c89initializerFieldsCount;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,17 +83,17 @@ export class CArrayType extends CType<CArrayTypeDescriptor> {
}

get itemScalarValuesCount() {
return this.baseType.scalarValuesCount;
return this.baseType.c89initializerFieldsCount;
}

get scalarValuesCount() {
const { scalarValuesCount } = this.baseType;
get c89initializerFieldsCount() {
const { c89initializerFieldsCount } = this.baseType;

if (this.isUnknownSize() || R.isNil(scalarValuesCount)) {
if (this.isUnknownSize() || R.isNil(c89initializerFieldsCount)) {
return null;
}

return this.size * scalarValuesCount;
return this.size * c89initializerFieldsCount;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export abstract class CType<T extends CTypeDescriptor = CTypeDescriptor>
return this.value.qualifiers;
}

get scalarValuesCount() {
get c89initializerFieldsCount() {
return 1;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class CStructType extends CType<CStructTypeDescriptor> {
return this.value.align;
}

get scalarValuesCount() {
get c89initializerFieldsCount() {
return this.getFlattenFieldsTypes().length;
}

Expand Down Expand Up @@ -86,7 +86,7 @@ export class CStructType extends CType<CStructTypeDescriptor> {
new CStructEntry({
...entry.unwrap(),
index: prevEntry
? prevEntry.index + prevEntry.type.scalarValuesCount
? prevEntry.index + prevEntry.type.c89initializerFieldsCount
: 0,
offset: alignerFn(this, entry.type),
bitset,
Expand Down Expand Up @@ -253,7 +253,7 @@ export class CStructType extends CType<CStructTypeDescriptor> {
return null;
}

getFieldTypeByIndex(index: number): CType {
getFieldTypeByC89InitializerIndex(index: number): CType {
return this.getFlattenFieldsTypes()[index]?.[1];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ export function isUnionLikeType(type: CType): type is CUnionType {

/**
* Defines C-like Union
*
* @see {@link https://www.ibm.com/docs/en/zos/2.2.0?topic=initializers-initialization-structures-unions}
*/
export class CUnionType extends CType<CUnionTypeDescriptor> {
static ofBlank(arch: CCompilerArch, name?: string) {
Expand All @@ -46,8 +48,13 @@ export class CUnionType extends CType<CUnionTypeDescriptor> {
return this.value.fields;
}

get scalarValuesCount() {
return this.getFlattenFieldsTypes().length;
/**
* According to standard only first field can be initialized using c89 initializer
*/
get c89initializerFieldsCount() {
const [, { type }] = this.getFieldsList()[0];

return type.c89initializerFieldsCount;
}

/**
Expand Down Expand Up @@ -198,7 +205,17 @@ export class CUnionType extends CType<CUnionTypeDescriptor> {
return this.getFlattenFieldsTypes().length;
}

getFieldTypeByIndex(index: number): CType {
return this.getFlattenFieldsTypes()[index]?.[1];
getFieldTypeByC89InitializerIndex(index: number): CType {
const [, { type }] = this.getFieldsList()[0];

if (isUnionLikeType(type) || type.isStruct()) {
return (type as any).getFieldTypeByC89InitializerIndex(index);
}

if (isArrayLikeType(type)) {
return type.baseType;
}

return type;
}
}
Loading

0 comments on commit 5ad4695

Please sign in to comment.