When the argument list of a function call is evaluated, the code generator can tell what arguments are missing by comparing the list to the function signature stored in the symbol table. Once you've discerned which argument needs to be replaced, it's just a matter of throwing the default value into the argument registers (or stack frame). If you're dealing with an OO language and the formal parameter is an object, you might push 0 (NULL) into the next word of the stack. If the parameter is a built-in primitive, you'll push whatever default value the language specifies.
Of course compilers can vary, but in a simplistic one, it's not absolutely necessary to associate a default value in the symbol table. First, lets be clear that a symbol table records all variable declarations. You must store information about those declarations (e.g. class, method, type, line, char, etc.), but surely there's no need to record a default value for each variable when there are only but a few types, and thus only a few possible default values.
Some languages (Java/C++) specify that a class with an uninitialized object attribute has a default value of NULL. In implementing something like that, when the code generator creates the class constructor, it'll be sure to generate code that places a 0 in the object memory mapped to that attribute (assume everything is pointer based). When you go to generate the constructor, and you're iterating over the class attribute list (an AST node), if there's no initialization expression for that attribute, call a method to do the default.
private void genConstructor(int classId) {
//allocate new object
codeGen.write("li $a0, "+classId);
codeGen.write("jal Runtime.newObject");
//call parent constructor
codeGen.write("move $a0, $v0");
codeGen.write("jal ParentInit");
//initialize the attributes this class has declared
for(Attributes a: getAttributes(classId)) {
//provide default value
if(a.getInitExpr() == null)
doDefault(a.getType(), a.getNum());
else
doInit(a.getInitExpr(), a.getNum());
}
}
// An 'Int' default value is 1, everything else is 0 (Objects included)
// $t0 has the object address
// attributes start at the 5th word of each object
private void doDefault(String type, int attrNum) {
switch(type) {
case "Int": {
codeGen.write("sw $one, "+(5+attrNum)+"($t0)");
}
default: {
codeGen.write("sw $zero, "+(5+attrNum)+"($t0)");
}
}
}
Update:
I am wondering how compiler handle the default value set by programmer
instead of "default" for "class" or "type".
I'm assuming you're speaking of something similar to default args in C++ constructors. In that case, as Ira mentioned, making a field in the symbol table record sounds like the simplest way to go about it. When generating the code for the missing argument, look up the default value in the table.