• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.
3  *
4  * HDF is dual licensed: you can use it either under the terms of
5  * the GPL, or the BSD license, at your option.
6  * See the LICENSE file in the root of this repository for complete details.
7  */
8 
9 #include <string.h>
10 #include <hcs_gener.h>
11 #include "hcs_compiler.h"
12 #include "hcs_file.h"
13 #include "hcs_opcode.h"
14 #include "hcs_log.h"
15 #include "hcs_option.h"
16 
17 #define DEBUG_PRINT_TAB_SIZE 2
18 
ByteCodeConvert(ParserObject * current,int32_t walkDepth)19 static int32_t ByteCodeConvert(ParserObject *current, int32_t walkDepth)
20 {
21     (void)walkDepth;
22     /* template should not output */
23     if (current->objectBase.type == PARSEROP_CONFNODE && current->configNode.nodeType == CONFIG_NODE_TEMPLATE) {
24         HcsAstRemoveChildLink(current->objectBase.parent, &current->objectBase);
25         HcsDeleteParserObjectTree(current);
26         return NOERR;
27     }
28     const OpCodeMapEntry *opcodeEntry = HcsParserObjectTypeToByteCode(current->objectBase.type);
29     if (opcodeEntry == NULL) {
30         return EFAIL;
31     }
32     current->objectBase.opCode = opcodeEntry->opCode;
33 
34     /* calculate leaf size when forward walk */
35     HcsCalculateOpcodeSize(current);
36 
37     return NOERR;
38 }
39 
DumpParserObjectValue(const ParserObject * obj)40 static void DumpParserObjectValue(const ParserObject *obj)
41 {
42     switch (obj->objectBase.opCode) {
43         case HCS_BYTE_OP:
44         case HCS_WORD_OP:
45         case HCS_DWORD_OP:
46         case HCS_QWORD_OP:
47             HCS_PRINT("%"PRIu64, obj->objectBase.integerValue);
48             break;
49         case HCS_STRING_OP:
50             HCS_PRINT("%s", obj->objectBase.stringValue);
51             break;
52         default:
53             break;
54     }
55 }
56 
OpCodeDumpPrint(ParserObject * current,int32_t walkDepth)57 static int32_t OpCodeDumpPrint(ParserObject *current, int32_t walkDepth)
58 {
59     int32_t printTab = walkDepth * DEBUG_PRINT_TAB_SIZE;
60     uint8_t opCode = current->objectBase.opCode;
61     uint32_t size = current->objectBase.size;
62     HCS_PRINT("%-10x%-15s%-10u%-10u%*c%-10s", opCode, HcsOpcodeToStr(current->objectBase.type), size,
63         current->objectBase.subSize, printTab, ' ', current->configNode.name);
64 
65     DumpParserObjectValue(current);
66     HCS_PRINT("\n");
67     return NOERR;
68 }
69 
DumpFinalAstWithOpCode()70 static void DumpFinalAstWithOpCode()
71 {
72     HCS_PRINT("\nDump final AST with OpCode\n");
73     HCS_PRINT("%-10s%-15s%-10s%-10s%*c%-20s\n", "OpCode", "OpCodeName", "Size", "SubSize", 1, ' ', "ObjectName");
74     HcsWalkAst(NULL, AST_WALK_FORWARD, OpCodeDumpPrint, NULL);
75 }
76 
ByteCodeWriteWalk(ParserObject * current,int32_t walkDepth)77 static int32_t ByteCodeWriteWalk(ParserObject *current, int32_t walkDepth)
78 {
79     (void)walkDepth;
80     current->objectBase.hash = HcsGetOutputCurrentCount();
81     if (HcsOutputWriteAlign(&current->objectBase.opCode, sizeof(current->objectBase.opCode))) {
82         return EOUTPUT;
83     }
84     int32_t ret = NOERR;
85     switch (current->objectBase.opCode) {
86         case HCS_BYTE_OP: /* fall-through */
87         case HCS_WORD_OP: /* fall-through */
88         case HCS_DWORD_OP: /* fall-through */
89         case HCS_QWORD_OP: {
90             const OpCodeMapEntry *byteCodeMap = HcsGetOpCodeMap();
91             ret = HcsOutputWriteAlign(&current->objectBase.integerValue, byteCodeMap[current->objectBase.type].size);
92             break;
93         }
94         case HCS_STRING_OP:
95             ret = HcsOutputWriteAlign(current->objectBase.stringValue, strlen(current->objectBase.stringValue) + 1);
96             break;
97         case HCS_TERM_OP:
98             ret = HcsOutputWriteAlign((void *)current->objectBase.name, strlen(current->objectBase.name) + 1);
99             break;
100         case HCS_NODE_OP:
101             if (HcsOutputWriteAlign((void *)current->objectBase.name, strlen(current->objectBase.name) + 1)) {
102                 return EOUTPUT;
103             }
104             ret = HcsOutputWriteAlign(&current->objectBase.subSize, sizeof(current->objectBase.subSize));
105             break;
106         case HCS_ARRAY_OP: {
107             uint16_t size = HcsCountArraySize(current);
108             ret = HcsOutputWriteAlign(&size, sizeof(size));
109         }
110             break;
111         case HCS_NODEREF_OP: {
112             ParserObject *ref = (ParserObject *)current->objectBase.value;
113             uint32_t hashCode = ref->objectBase.hash;
114             ret = HcsOutputWriteAlign(&hashCode, sizeof(hashCode));
115         }
116             break;
117         default:
118             break;
119     }
120 
121     return ret;
122 }
123 
HcsBytecodeOutput(void)124 int32_t HcsBytecodeOutput(void)
125 {
126     ParserObject *astRoot = HcsGetParserRoot();
127     if (astRoot == NULL) {
128         return EFAIL;
129     }
130 
131     /* generate OpCode for every object on AST and calculate size for each object */
132     int32_t ret = HcsWalkAst(astRoot, AST_WALK_BACKEND, NULL, ByteCodeConvert);
133     if (ret) {
134         return ret;
135     }
136 
137     /* ast data is ready, do bindary output */
138     struct HcsFile *outputFIle = HcsOpenOutputFile(HCS_OUTPUT_FILE_SUFFIX);
139 
140     HbcHeader header = {
141         .magicNumber = HBC_MAGIC_NUM,
142         .checkSum = 0,
143         .totalSize = HcsOptShouldAlign() ? -astRoot->objectBase.size : astRoot->objectBase.size,
144         .versionMajor = HCS_COMPILER_VERSION_MAJOR,
145         .versionMinor = HCS_COMPILER_VERSION_MINOR,
146     };
147 
148     HcsMockOutPut(true);
149     /* Generate hashcode for each object */
150     if (HcsOutputWriteAlign(&header, sizeof(header))) {
151         HcsCloseOutput(outputFIle);
152         return EOUTPUT;
153     }
154     ret = HcsWalkAst(astRoot, AST_WALK_FORWARD, ByteCodeWriteWalk, NULL);
155     if (ret) {
156         HcsCloseOutput(outputFIle);
157         return ret;
158     }
159     HcsResetOutputCurrentCount();
160     HcsMockOutPut(false);
161 
162     if (HcsVerbosePrint()) {
163         DumpFinalAstWithOpCode();
164     }
165 
166     /* write bytecode to output file */
167     if (HcsOutputWriteAlign(&header, sizeof(header))) {
168         HcsCloseOutput(outputFIle);
169         return EOUTPUT;
170     }
171     ret = HcsWalkAst(astRoot, AST_WALK_FORWARD, ByteCodeWriteWalk, NULL);
172 
173     /* verify file size */
174     uint64_t fileSize = HcsSourceFileGetSize(outputFIle);
175     if (fileSize != (sizeof(header) + abs(header.totalSize))) {
176         HCS_ERROR("output file size mismatch");
177         ret = EOUTPUT;
178     }
179 
180     HcsCloseOutput(outputFIle);
181     HCS_DEBUG("Total size: %u ", astRoot->objectBase.size);
182     if (ret == NOERR && HcsOptShouldGenHexdump()) {
183         ret = HcsBinaryToHexdump(HcsGetOutPutFilePath());
184     }
185     return ret;
186 }
187