public Value BuildBr(Block block, AST.Node contextNode) { var result = new Value(Op.Br, null, block); AddOp(result, contextNode: contextNode); return(result); }
public Value BuildRet(Value ret, AST.Node contextNode) { var result = new Value(Op.Ret, ret.type, ret); AddOp(result, contextNode: contextNode); return(result); }
public Value BuildRetVoid(AST.Node contextNode) { var result = new Value(Op.Ret, Const.void_t); AddOp(result, contextNode: contextNode); return(result); }
public Value BuildExtractValue(Value v, AST.Node contextNode, string name = null, params Value[] indices) { Debug.Assert(indices != null && indices.Length > 0); var result = new Value(Op.ExtractValue, null, v); result.args.AddRange(indices); Debug.Assert(indices != null && indices.Length > 0); Debug.Assert(indices[0].type.kind == TypeKind.Integer); SSAType resultType = v.type; for (int i = 0; i < indices.Length; ++i) { var idx = indices[i]; Debug.Assert(idx.type.kind == TypeKind.Integer); if (resultType.kind == TypeKind.Array) { resultType = ((ArrayType)resultType).elementType; } else if (resultType.kind == TypeKind.Struct) { Debug.Assert(idx.isConst); var elementIdx = (int)(idx as ConstInt).data; var st = (StructType)resultType; resultType = st.elementTypes[elementIdx]; } } result.type = resultType; result.isConst = v.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildCall(Value fun, AST.Node contextNode, string name = null, params Value[] args) { Debug.Assert(fun.type.kind == TypeKind.Pointer); var ft = (fun.type as PointerType).elementType as FunctionType; Debug.Assert(ft != null); var result = new Value(Op.Call, ft, fun); if (args != null && args.Length > 0) { result.args.AddRange(args); } result.type = ft.returnType; if (result.type.kind != TypeKind.Void) { AddOp(result, name, contextNode: contextNode); } else { AddOp(result, contextNode: contextNode); } return(result); }
public Value BuildCondBr(Value cond, Block ifTrue, Block ifFalse, AST.Node contextNode) { Debug.Assert(SSAType.IsBoolType(cond.type)); var result = new Value(Op.Br, null, cond, ifTrue, ifFalse); AddOp(result, contextNode: contextNode); return(result); }
public Value BuildBitCast(Value v, SSAType dest, AST.Node contextNode, string name = null) { var result = new Value(Op.BitCast, dest, v); result.isConst = v.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public GetElementPtr BuildGEP(Value ptr, AST.Node contextNode, string name = null, bool inBounds = false, params Value[] indices) { var result = new GetElementPtr(ptr, inBounds, indices); result.isConst = ptr.isConst && indices.All(idx => idx.isConst); AddOp(result, name, contextNode: contextNode); return(result); }
public GetElementPtr BuildStructGEP(Value structPointer, int idx, AST.Node contextNode, string name = null) { var result = new GetElementPtr(structPointer, true, zero_i32_v, new ConstInt(i32_t, (ulong)idx)); result.isConst = structPointer.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildNot(Value v, AST.Node contextNode, string name = null) { var result = new Value(Op.Not, v.type, v); result.isConst = v.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public ICmp BuildICmp(Value left, Value right, IcmpType icmpType, AST.Node contextNode, string name = null) { var result = new ICmp(left, right, icmpType, name); result.isConst = left.isConst && right.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildFRem(Value left, Value right, AST.Node contextNode, string name = null) { var result = new Value(Op.FRem, left.type, left, right); result.isConst = left.isConst && right.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildFCmp(Value left, Value right, FcmpType fcmpType, AST.Node contextNode, string name = null) { var result = new FCmp(left, right, fcmpType, name); result.isConst = left.isConst && right.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildPtrToInt(Value v, SSAType integerType, AST.Node contextNode, string name = null) { var result = new Value(Op.PtrToInt, integerType, v); result.isConst = v.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildIntToPtr(Value v, SSAType pointerType, AST.Node contextNode, string name = null) { var result = new Value(Op.IntToPtr, pointerType, v); result.isConst = v.isConst; AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildArrayAlloca(SSAType t, Value size, AST.Node contextNode, string name = null) { var result = new Value(Op.Alloca, new PointerType(t), size); result.alignment = 16; Debug.Assert(size.type.kind == TypeKind.Integer); AddOp(result, name, contextNode: contextNode); return(result); }
public Value BuildSizeOf(SSAType t, AST.Node contextNode, string name = null) { var np = new ConstPtr(new PointerType(t), 0); var size = BuildGEP(np, contextNode, "size_of_trick", false, one_i32_v); var result = BuildPtrToInt(size, Const.mm_t, contextNode, name); Debug.Assert(result.isConst); return(result); }
public Value BuildGlobalStringPtr(string str, AST.Node contextNode, string name = null) { var gs = new GlobalStringPtr(str); AddOpGlobal(gs, name, contextNode: contextNode); var result = BuildBitCast(gs, ptr_t, contextNode); Debug.Assert(result.isConst); return(result); }
void AddOpGlobal(Value v, string name, AST.Node contextNode = null) { Debug.Assert(v is GlobalVariable || v is GlobalStringPtr || v is Function); if (name != null) { v.name = context.RequestGlobalName(name); } mod.globals.args.Add(v); v.debugContextNode = contextNode; }
public Value BuildAlloca(SSAType t, AST.Node contextNode, string name = null, int align = 0) { if (align > 32) { align = 32; } var result = new Value(Op.Alloca, new PointerType(t)); result.alignment = align; AddOp(result, name, contextNode: contextNode); return(result); }
public GlobalVariable AddGlobal(SSAType t, AST.Node contextNode, string name = null, bool isConst = false, int align = 0) { if (align > 16) { align = 16; } var result = new GlobalVariable(t, isConst); result.alignment = align; AddOpGlobal(result, name, contextNode: contextNode); return(result); }
public Value BuildMemCpy(Value destPtr, Value srcPtr, Value count, AST.Node contextNode, bool isVolatile = false) { Value isVolatile_v; if (isVolatile) { isVolatile_v = true_v; } else { isVolatile_v = false_v; } var result = BuildCall(intrinsic_memcpy, contextNode, "memcpy", destPtr, srcPtr, count, zero_i32_v, isVolatile_v); return(result); }
public Value BuildStore(Value v, Value ptr, AST.Node contextNode, bool isVolatile = false, int align = 0) { if (align > 16) { align = 16; } Debug.Assert(ptr.type.kind == TypeKind.Pointer); var result = new Value(Op.Store, null, v, ptr); result.alignment = align; if (isVolatile) { result.flags |= SSAFlags.@volatile; } AddOp(result, contextNode: contextNode); return(result); }
public Value BuildLoad(Value ptr, AST.Node contextNode, string name = null, bool isVolatile = false, int align = 0) { if (align > 16) { align = 16; } Debug.Assert(ptr.type.kind == TypeKind.Pointer); var pt = (PointerType)ptr.type; var result = new Value(Op.Load, pt.elementType, ptr); result.alignment = align; if (isVolatile) { result.flags |= SSAFlags.@volatile; } AddOp(result, name, contextNode: contextNode); return(result); }
void AddOp(Value v, string name = null, Function f = null, AST.Node contextNode = null) { if (!v.isConst) { if (name != null) { v.name = context.RequestLocalName_(name, f); } context.currentBlock.args.Add(v); } if (context.callsite == null) { v.debugContextNode = contextNode; } else { v.debugContextNode = context.callsite; } }
//----------------------------------------------------------------------------- // This construct must be inside a loop //----------------------------------------------------------------------------- public static SymbolErrorException MustBeInsideLoop(AST.Node node) { string stHint = "?"; if (node is AST.BreakStatement) { stHint = "break"; } else if (node is AST.ContinueStatement) { stHint = "continue"; } else { Debug.Assert(false, "Illegal type:" + node.GetType()); } return(new SymbolErrorException( Code.cMustBeInsideLoop, node.Location, "'" + stHint + "' must occur inside a control block (do, while, for)" )); }
public static AST.Node FindNode(Scope scope, int posZeroBased, int lineZeroBased, string filePath) { AST.Node FindNodeRec(AST.Node node, int pos, int line) { if (node.token.filename != filePath) { return(null); } if (InsideToken(node.token, pos, line)) { return(node); } else { if (node is AST.FieldAccess fa) { if (InsideToken(fa.fieldNameToken, pos, line)) { return(node); } } foreach (var child in node.GetChilds()) { var result = FindNodeRec(child, pos, line); if (result != null) { return(result); } } } return(null); } AST.Node result = FindNodeRec(scope.owner, posZeroBased + 1, lineZeroBased + 1); return(result); }
public ArrayInitializer(Node[] list) { m_list= list; }
public Value BuildFNeg(Value v, AST.Node contextNode, string name = null) { return(BuildFSub(ConstNull(v.type), v, contextNode, name)); }
// Utility to Dump to XML file public static void DumpTree(Node root, XmlWriter o) { o.WriteStartDocument(); o.WriteStartElement("AST"); root.Dump(o); o.WriteEndElement(); // AST o.WriteEndDocument(); o.Close(); }
public Value BuildNeg(Value v, AST.Node contextNode, string name = null) { Debug.Assert(v.type.kind == TypeKind.Integer); return(BuildSub(ConstNull(v.type), v, contextNode, name)); }
// Debugging facility. Dump() spits out XML which can be really tough to read, // and it's not clear what it should include. // So we have a facility to spit it out as a string. static string GetAsSourceString(Node n) { //System.Text.StringBuilder sb = new System.Text.StringBuilder(); //n.ToSource(sb); //return sb.ToString(); return "empty"; }
public static void DumpSourceToStream(Node n, System.IO.TextWriter t) { Console.WriteLine("*** Begin Source dump: ["); System.CodeDom.Compiler.IndentedTextWriter i = new System.CodeDom.Compiler.IndentedTextWriter(t, " "); n.ToSource(i); Console.WriteLine("] *** End source dump"); i.Close(); i = null; }
// Dump the string to the console. public static void DumpSource(Node n) { DumpSourceToStream(n, Console.Out); }
// Create an array initializer from the list public ArrayInitializer(System.Collections.ArrayList al) { m_list = new Node[al.Count]; for(int i = 0; i < m_list.Length; i++) m_list[i] = (Node) al[i]; }
public Phi BuildPhi(SSAType t, AST.Node contextNode, string name = null, params (Value, Block)[] incoming)
// Semantic resolution protected override Exp ResolveExpAsRight(ISemanticResolver s) { // Only resolve once. if (m_symbol != null) return this; // First, resolve our parameters (because of overloading) // We need to know the URT types for our parameters // in order to resolve between overloaded operators Type [] alParamTypes = new Type[m_arParams.Length]; for(int i = 0; i < m_arParams.Length; i++) { Exp e = m_arParams[i]; ResolveExpAsRight(ref e, s); Debug.Assert(e == m_arParams[i]); Type tParam = e.CLRType; //if ((tParam !=null) && tParam.IsByRef) // tParam = tParam.GetElementType(); alParamTypes[i] = tParam; //Debug.Assert(alParamTypes[i] != null); } TypeEntry tCur = s.GetCurrentClass(); TypeEntry tLeft = null; // Type to lookup in // Is this a 'base' access? // Convert to the real type and set a non-virtual flag if (m_objExp is SimpleObjExp) { SimpleObjExp e = m_objExp as SimpleObjExp; if (e.Name.Text == "base") { // Set the scope that we lookup in. tLeft = tCur.Super; // Still need to resolve the expression. m_objExp = new SimpleObjExp("this"); m_fIsNotPolymorphic = true; } } #if true // See if we have a delegate here Exp eDelegate = null; if (m_objExp == null) { Exp e = new SimpleObjExp(m_idName); Exp.ResolveExpAsRight(ref e, s); if (!(e is SimpleObjExp)) eDelegate = e; } else { // If it's an interface, then we know we can't have a delegate field on it, // so short-circuit now. Exp.ResolveExpAsRight(ref m_objExp, s); if (!m_objExp.CLRType.IsInterface) { Exp e = new DotObjExp(m_objExp, m_idName); Exp.ResolveExpAsRight(ref e, s); if (!(e is DotObjExp)) eDelegate = e; } } if (eDelegate != null) { if (!DelegateDecl.IsDelegate(eDelegate.CLRType)) { //Debug.Assert(false, "@todo - " + m_strName + " is not a delegate or function"); // @todo - legit // Just fall through for now, method resolution will decide if this is a valid function } else { Exp e = new MethodCallExp( eDelegate, new Identifier("Invoke"), this.m_arParams ); Exp.ResolveExpAsRight(ref e, s); return e; } } #endif // No delegate, carry on with a normal function call // If there's no objexp, then the function is a method // of the current class. // make it either a 'this' or a static call if (m_objExp == null) { // Lookup bool fIsVarArgDummy; MethodExpEntry sym = tCur.LookupMethod(s, m_idName, alParamTypes, out fIsVarArgDummy); if (sym.IsStatic) { m_objExp = new TypeExp(tCur); } else { m_objExp = new SimpleObjExp("this"); } } // Need to Lookup m_strName in m_objExp's scope (inherited scope) Exp.ResolveExpAsRight(ref m_objExp, s); // Get type of of left side object // This call can either be a field on a variable // or a static method on a class bool fIsStaticMember = false; // If we don't yet know what TypeEntry this methodcall is on, then figure // it out based off the expression if (tLeft == null) { if (m_objExp is TypeExp) { fIsStaticMember = true; tLeft = ((TypeExp) m_objExp).Symbol; } else { fIsStaticMember = false; tLeft = s.ResolveCLRTypeToBlueType(m_objExp.CLRType); } } // Here's the big lookup. This will jump through all sorts of hoops to match // parameters, search base classes, do implied conversions, varargs, // deal with abstract, etc. bool fIsVarArg; m_symbol = tLeft.LookupMethod(s, m_idName, alParamTypes, out fIsVarArg); Debug.Assert(m_symbol != null); if (m_fIsNotPolymorphic) { // of the form 'base.X(....)' if (m_symbol.IsStatic) ThrowError(SymbolError.BaseAccessCantBeStatic(this.Location, m_symbol)); // @todo - PrintError? } else { // normal method call /* if (fIsStaticMember && !m_symbol.IsStatic) ThrowError(SymbolError.ExpectInstanceMember(this.Location)); // @todo - PrintError? else if (!fIsStaticMember && m_symbol.IsStatic) ThrowError(SymbolError.ExpectStaticMember(this.Location)); // @todo - PrintError? */ Debug.Assert(fIsStaticMember == m_symbol.IsStatic, "@todo - user error. Mismatch between static & instance members on line."); } // If we have a vararg, then transform it if (fIsVarArg) { // Create the array int cDecl = m_symbol.ParamCount; int cCall = this.ParamExps.Length; ArrayTypeSig tSig = new ArrayTypeSig(m_symbol.ParamCLRType(cDecl - 1), s); Node [] list = new Node[cCall - cDecl + 1]; for(int i = 0; i < list.Length; i++) { list[i] = this.ParamExps[i + cDecl - 1]; } Exp eArray = new NewArrayObjExp( tSig, new ArrayInitializer( list ) ); Exp.ResolveExpAsRight(ref eArray, s); // Change the parameters to use the array ArgExp [] arParams = new ArgExp[cDecl]; for(int i = 0; i < cDecl - 1; i++) arParams[i] = m_arParams[i]; arParams[cDecl - 1] = new ArgExp(EArgFlow.cIn, eArray); m_arParams = arParams; } // end vararg transformation this.CalcCLRType(s); return this; }