def _addHelperFunctionsPostTranslation(self): # if this module contains a main function emit code which will call it flist = self._findSymbol(name=u'main', type_=ESFunction, mayFail=True) if flist: assert(len(flist) == 1) esMain = flist[0] s = [] s.append('The main function defined in this module has an unsupported signature.') s.append('supported signatures:') s.append('\tdef main() as int32') s.append('\tdef main() as void') int32 = self._findSymbol(name=u'int32', type_=ESType) void = self._findSymbol(name=u'void', type_=ESType) validA = ESType.createFunction([int32], []) validB = ESType.createFunction([void], []) ok = False for x in [validA, validB]: if x.isEquivalentTo(esMain.esType, False): ok = True if not ok: self._raiseException(RecoverableCompileError, postText=s) # has arguments? if len(esMain.esType.getFunctionParameterTypes()) == 0: functionType= Type.function(Type.int(32), []) function = self._module.add_function(functionType, 'main') entryBB = function.append_basic_block('entry') BB = function.append_basic_block('bb') b = Builder.new(entryBB) if self._debugMode: dbgSubProg = self._debugInfoBuilder.addFunctionInfoStart(module=self._module, builder=b, lineNumber=0, name='main', displayName='main') b.branch(BB) b = Builder.new(BB) r = b.call(esMain.llvmRef, []) retTypes = esMain.esType.getFunctionReturnTypes() assert(len(retTypes) == 1) if retTypes[0].toLLVMType() != Type.void(): b.ret(r) else: b.ret(Constant.int(Type.int(32), 0)) if self._debugMode: self._debugInfoBuilder.addFunctionInfoEnd(module=self._module, builder=b, subprogram=dbgSubProg) else: # TODO implement version with parameters self._raiseException(RecoverableCompileError, postText=s)
def _onFuncPrototype(self, ast, modifierKeys, modifierValues, name, returnTypeName, parameterNames, parameterTypeNames, block): # create type of function self._dispatch(returnTypeName) returnTypes = [returnTypeName.esType] paramNames = [] paramTypes = [] for i in range(len(parameterTypeNames)): paramNames.append(parameterNames[i].text) self._dispatch(parameterTypeNames[i]) paramTypes.append(parameterTypeNames[i].esType) functionType = ESType.createFunction(returnTypes, paramTypes) # parse modifiers linkage = None mangling = None for i in range(len(modifierKeys)): k = modifierKeys[i].text v = modifierValues[i].text if k == u'linkage': linkage = v elif k == u'mangling': mangling = v else: self._raiseException(RecoverableCompileError, tree=modifierKeys[i], inlineText='unknown function modifier') esFunction = ESFunction(name.text, self._moduleNode.packageName, self._moduleNode.moduleName, functionType, paramNames, mangling=mangling, linkage=linkage) ast.esFunction = esFunction ast.esType = functionType if name.text in ['ctor', 'dtor']: # function is a constructor / destructor # TODO allow only global functions to be module constructors / destructors moduleXTor = True if moduleXTor: # module XTors must have the signature 'def Xtor() as void' expectedType = ESType.createFunction([self._findSymbol(name=u'void', type_=ESType)], []) if not functionType.isEquivalentTo(expectedType, True): # structurally / name based should not matter for module Xtors self._raiseException(RecoverableCompileError, tree=name, inlineText='a module ctor / dtor must have the type \'def Xtor() as void\'') if name.text == 'ctor': self._moduleCTors.append(esFunction) else: self._moduleDTors.append(esFunction) # TODO check for duplicate entries self._addSymbol(fromTree=name, symbol=esFunction)
def _addHelperFunctionsPreTranslation(self): # int puts(char *); returnTypes = [self._findSymbol(name=u'int32', type_=ESType)] paramTypes = [self._findSymbol(name=u'int8', type_=ESType).derivePointer()] esType = ESType.createFunction(returnTypes, paramTypes) esFunc = ESFunction(u'puts', '', '', esType, [u's'], mangling='C', linkage='extern') self._addSymbol(name=u'puts', symbol=esFunc) type = esType.toLLVMType() func = self._module.add_function(type, 'puts') # void abort(); returnTypes = [self._findSymbol(name=u'void', type_=ESType)] paramTypes = [] esType = ESType.createFunction(returnTypes, paramTypes) esFunc = ESFunction(u'abort', '', '', esType, [], mangling='C', linkage='extern') type = esType.toLLVMType() func = self._module.add_function(type, 'abort')
def _onFunctionTypeName(self, ast): # FIXME move ast unpacking to AstWalker! types = [] for x in ast.children: self._dispatch(x) types.append(x.esType) esType = ESType.createFunction([types[-1]], types[:-1]) esType = esType.derivePointer() ast.esType = esType
def _onDefStruct(self, ast, name, members): # since structs can refer to them selves using pointers we have to add this type right now structType = ESType.createStruct(name.text, [], []) self._addSymbol(fromTree=name, symbol=structType) esTypes = [] names = [] for x in members: # DO NOT dispatch x itself! that would add entries to a symbol table that does not exist # process name manually and dispatch type name self._dispatch(x.children[1]) esTypes.append(x.children[1].esType) if x.children[0].text in names: self._raiseException(RecoverableCompileError, tree=x.children[0], inlineText='name already used') names.append(x.children[0].text) # add members # FIXME derive type name from package and module! t = ESType.createStruct(name.text, esTypes, names) structType.payload = t.payload structType.parents = t.parents ast.esType = structType
def _onTypeName(self, ast): def insideStructDef(self): sdn = None for n in reversed(self._nodes): if n.type == TreeType.STRUCT: sdn = n break return sdn n = len(ast.children) if n == 1: ast.esType = self._findSymbol(fromTree=ast.children[0], type_=ESType) if ast.esType.isStruct() and not ast.esType.parents: assert(insideStructDef(self)) self._raiseException(RecoverableCompileError, fromTree=ast, inlineText='structs can not contain themself. Use a pointer') else: # later we could implement here const / invariant etc. # but now just look up name baseType = self._findSymbol(fromTree=ast.children[0], type_=ESType) if baseType.isStruct() and not baseType.parents: assert(insideStructDef(self)) baseType = ESType.createSelfPointer() # no nesting allowed for now! if ast.children[1].type not in [TreeType.STAR, TreeType.DOUBLESTAR]: self._raiseException(RecoverableCompileError, tree=ast.children[1], inlineText='type constructors are not supported') for x in ast.children[1:]: baseType = baseType.derivePointer() if x.type == TreeType.DOUBLESTAR: baseType = baseType.derivePointer() ast.esType = baseType
def _onNoneConstant(self, ast): ast.esType = ESType.createNone()